Доступна система управления исходными текстами Git 2.41

После трёх месяцев разработки опубликован выпуск распределенной системы управления исходными текстами Git 2.41. Git является одной из самых популярных, надёжных и высокопроизводительных систем управления версиями, предоставляющей гибкие средства нелинейной разработки, базирующиеся на ответвлении и слиянии веток. Для обеспечения целостности истории и устойчивости к изменениям “задним числом” используются неявное хеширование всей предыдущей истории в каждом коммите, также возможно удостоверение цифровыми подписями разработчиков отдельных тегов и коммитов.

По сравнению с прошлым выпуском в новую версию принято 542 изменения, подготовленные при участии 95 разработчиков, из которых 29 впервые приняли участие в разработке. Основные новшества:

  • Улучшена обработка недостижимых объектов (unreachable), на которые в репозитории отсутствуют ссылки (не ссылаются ветки или теги). Недостижимые объекты удаляются сборщиком мусора, но до удаления определённое время остаются в репозитории для исключения состояний гонки. Для отслеживания периода нахождения недостижимых объектов необходима привязка к ним меток с временем изменения подобных объектов, что не позволяет хранить их в одном pack-файле, в котором все объекты имеют общее время изменения. Ранее применяемое сохранение каждого объекта в отдельном файле приводило к проблемам при наличии большого числа свежих недостижимых объектов, ещё не подпадающих под удаление. В новом выпуске для упаковки недостижимых объектов по умолчанию задействован механизм “cruft packs“, позволяющий хранить все недостижимые объекты в одном pack-файле, а данные о времени модификации каждого объекта отражать в отдельной таблице, хранимой в файле с расширением “.mtimes” и связываемой при помощи индексного файла с расширением “.idx”.

  • Включено по умолчанию ведение на диске обратного индекса (revindex) для pack-файлов. При тестировании на репозитории torvalds/linux применение обратного индекса позволило ускорить ресурсоёмкие операции “git push” в 1.49 раза, а простые операции, такие как вычисление размера одного объекта при помощи “git cat-file –batch=’%(objectsize:disk)'” в 77 раз. Файлы (“.rev”) с обратным индексом будут сохранены внутри репозитория в каталоге
    “.git/objects/pack”.

    Напомним, что Git хранит все данные в форме объектов, которые размещаются в отдельных файлах. Для повышения эффективности работы с репозиторием объекты дополнительно помещаются в pack-файлы, в которых информация представлена в форме потока из объектов, следующих друг за другом (аналогичный формат используется при передаче объектов командами git fetch и git push). Для каждого pack-файла создаётся индексный файл (.idx), позволяющий по идентификатору объекта очень быстро определить смещение в pack-файле, по которому хранится данный объект.

    Включённый в новом выпуске обратный индекс нацелен на оптимизацию процесса определения идентификатора объекта по информации о размещении объекта в pack-файле. Ранее такое преобразование выполнялось на лету во время разбора pack-файла и хранилось только в памяти, что не позволяло повторно использовать подобные индексы и вынуждало генерировать индекс каждый раз. Операция построения индекса сводится к построению массива из пар “объект-позиция” и его сортировке по позиции, что может занимать много времени для больших pack-файлов.

    Например, операция вывода содержимого объектов, в которой используется прямой индекс, выполнялась в 62 раза быстрее, чем операция показа размера объектов, для которой данные о связи позиции с объектом не индексировались. После использования обратного индекса указанные операции стали занимать примерно одинаковое время. Обратные индексы также позволяют ускорить операции отправки объектов при выполнении команд fetch и push за счёт прямой передачи уже готовых данных с диска.


  • В протокол “credential helper“, применяемый для передачи учётных данных
    при обращения к репозиторям c ограниченным доступом, добавлена поддержка передачи заголовков WWW-Authenticate между обработчиком учётных данных и сервисом, в котором производится аутентификация. Поддержка заголовка WWW-Authenticate позволяет передавать scope-параметры OAuth для более гранулированного разделения доступа пользователя к репозиториям и разграничения областей, доступных для запросов.
  • В команду for-each-ref добавлена опция форматирования “%(ahead-behind:)”, позволяющая разом получить сведения о числе коммитов, присутствующих или отсутствующих в определённой ветке, относительно другой ветки (на сколько одна ветка отстаёт или опережает другую на уровне коммитов). Ранее для получения подобной информации требовалось выполнить две отдельные команды: “git rev-list –count main..my-feature” для получения числа уникальных для ветки коммитов и “git rev-list –count my-feature..main” для получения числа отсутствующих коммитов. Теперь подобные вычисления можно свести к одной команде, что упрощает написание обработчиков и сокращает время выполнения. Например для показа не прошедших слияния веток и оценки отставания или опережения их основной ветки можно использовать однострочник: $ git for-each-ref –no-merged=origin/HEAD –format=’%(refname:short) %(ahead-behind:origin/HEAD)’ refs/heads/tb/ | column -t tb/cruft-extra-tips 2 96 tb/for-each-ref–exclude 16 96 tb/roaring-bitmaps 47 3
    вместо ранее применявшегося скрипта, который выполняется в 17 раз медленнее: $ git for-each-ref –format=’%(refname:short)’ –no-merged=origin/HEAD refs/heads/tb | while read ref do ahead=”$(git rev-list –count origin/HEAD..$ref)” behind=”$(git rev-list –count $ref..origin/HEAD)” printf “%s %d %dn” “$ref” “$ahead” “$behind” done | column -t tb/cruft-extra-tips 2 96 tb/for-each-ref–exclude 16 96 tb/roaring-bitmaps 47 3
  • В команду “git fetch” добавлена опция “–porcelain”, при указании которой формируется вывод в формате “”, менее читаемый, но более удобный для разбора в скриптах.
  • Добавлена настройка “fetch.hideRefs”, позволяющая ускорить операции
    “git fetch” за счёт скрытия части ссылок в локальном репозитории на стадии проверки отправки сервером полного набора объектов, что позволяет сэкономить время, ограничив проверку только серверов, с которого напрямую извлекаются данные. Например, при проведении теста на системе с репозиториями, содержащими большое число отслеживаемых внешних ссылок, исключение все ссылок кроме, адресованных целевому серверу $remote, позволило сократить выполнение операции “git fetch” с 20 минут до 30 секунд. $ git -c fetch.hideRefs=refs -c fetch.hideRefs=!refs/remotes/$remote fetch $remote
  • В команде “git fsck” реализована возможность проверки повреждений, соответствия контрольных сумм и корректности значений в битовых картах доступности и обратных индексах.
  • В команде “git clone –local” реализован вывод ошибки при попытке копирования из репозитория, содержащего символические ссылки внутри $GIT_DIR.

Release. Ссылка here.