Git 2.56: ускорение больших репозиториев, новые команды и улучшения работы слияния
Представлен новый релиз распределённой системы управления исходным кодом Git 2.56. В новую версию вошли 748 изменений, подготовленных при участии 104 разработчиков, в том числе 39 новых участников проекта. Исходный код Git распространяется под лицензией GPLv2+.
Одной из главных особенностей Git 2.56 стало существенное повышение производительности при работе с большими репозиториями. Кроме того, разработчики добавили новые возможности для разрешения конфликтов, управления ветками и ссылками, перепаковки объектов, анализа истории и автоматизации git bisect.
Git 2.56 ускоряет поиск общих предков при слиянии
В Git 2.56 значительно оптимизирован алгоритм поиска последних общих коммитов при слиянии веток и сравнении истории.
Теперь при обходе истории учитываются коммиты, принадлежащие только одной из сравниваемых веток. Благодаря этому Git может завершить поиск сразу после обнаружения всех возможных общих предков, не продолжая ненужное сканирование истории.
На протестированных репозиториях ускорение достигало 20–70 раз. Например, при выполнении:
git merge-base --all v4.8 v4.9
в репозитории ядра Linux количество шагов обхода сократилось примерно со 167 тысяч до 3,8 тысячи.
Новый режим git add --resolved для разрешения конфликтов
Git 2.56 получил команду:
git add --resolved
Новый режим предназначен для безопасного завершения разрешения конфликтов после слияния веток.
Перед добавлением файлов в индекс Git проверяет их на наличие маркеров конфликта. Если хотя бы в одном файле обнаружен такой маркер, операция завершается с ошибкой: файлы не индексируются, а пользователю показывается список файлов, требующих исправления.
В отличие от git add --update, новый режим работает только с файлами, находящимися непосредственно в состоянии конфликта. Другие изменённые файлы, не связанные со слиянием, игнорируются.
Это особенно удобно в случаях, когда в рабочем каталоге одновременно находятся незавершённые изменения, не относящиеся к текущему merge.
--path-walk: более компактные pack-файлы
Режим перепаковки:
git repack --path-walk
ранее рассматривался преимущественно как экспериментальная возможность, а теперь получил дополнительные возможности для серверного использования.
--path-walk группирует объекты по их расположению в дереве каталогов, что позволяет создавать более компактные pack-файлы.
В репозитории Fluent UI применение этого режима позволило уменьшить размер pack-файла с 558 МБ до 164 МБ.
В Git 2.56 --path-walk можно использовать совместно с reachability bitmap и delta islands — технологиями, широко применяемыми Git-хостингами для ускорения операций и изоляции форков от основного репозитория.
Значительное ускорение reftable и git diff
В Git 2.56 устранён ряд узких мест, особенно заметных в крупных репозиториях.
Разработчики оптимизировали:
запись данных в reftable;
добавление новых pack-файлов;
работу с большим количеством удалённых записей в reftable;
git diff при использовании ограничений по путям файлов.
На одном из тестов операции с reftable, содержащим большое количество удалений, ускорились с 13 секунд до 0,2 секунды, то есть примерно в 65 раз.
Ещё более заметный результат получен для git diff в репозитории Chromium с индексом, содержащим около 500 000 элементов: время выполнения проблемной операции сократилось примерно с 8 минут до 0,07 секунды.
git history drop: удаление коммита из истории
Экспериментальная команда:
git history
получила новую операцию:
git history drop
Она позволяет удалить выбранный коммит из истории, автоматически подключив его потомков непосредственно к родительскому коммиту.
Функция предназначена для операций по переписыванию истории Git и пока относится к экспериментальным возможностям.
Безопасное удаление объединённых веток
Git 2.56 добавляет возможность удалять сразу группы локальных веток, изменения которых уже были переданы во внешний репозиторий:
git branch --delete-merged 'origin/*' 'topic-*'
Для выбора веток и репозиториев можно использовать маски. Перед фактическим удалением список подходящих веток можно проверить с помощью:
--dry-run
Это позволяет безопасно контролировать очистку локального репозитория от больше не нужных веток.
Новая команда git refs
Для управления ссылками Git появилась команда:
git refs
Она объединяет низкоуровневые операции создания, изменения, удаления и переименования ссылок:
git refs create
git refs update
git refs delete
git refs rename
Это предоставляет более унифицированный интерфейс для работы с refs.
Улучшения git bisect run
В git bisect run появилась опция:
--reset-when-found=[<where>]
Она позволяет автоматически вернуть репозиторий в состояние, существовавшее до начала поиска, либо оставить найденный проблемный коммит активным.
Благодаря этому после завершения автоматического поиска больше не требуется отдельно выполнять git bisect reset.
Новый режим git replay --linearize
Команда:
git replay
получила флаг:
--linearize
Он позволяет использовать плоскую топологию истории слияний, аналогичную поведению:
git rebase --no-rebase-merges
При этом git replay --linearize выполняет операцию без обращения к рабочему дереву.
git log --follow теперь лучше работает со слияниями
В Git 2.56 улучшено отслеживание переименований файлов с помощью:
git log --follow
Теперь переименование может корректно отслеживаться и в нелинейной истории, например при наличии слияний подветок.
Путь к файлу фиксируется отдельно для каждого родительского коммита. Благодаря этому результат анализа становится независимым от порядка обхода истории.
Удаление ненужных больших blob-объектов
Git 2.56 позволяет использовать:
git repack -a --filter=blob:limit=1m --drop-filtered
для удаления крупных blob-объектов, которые были загружены из внешнего репозитория по требованию, но больше не используются в текущем индексе.
Если такой объект снова потребуется, Git сможет автоматически загрузить его повторно.
Это особенно полезно для репозиториев с большим количеством крупных файлов и сценариев частичной загрузки данных.
Улучшенный граф истории в git log --graph
В команде:
git log --graph
улучшено отображение историй с несколькими независимыми корнями.
Для визуального разделения несвязанных ветвей истории теперь используются дополнительные отступы, благодаря чему сложные графы коммитов становятся более понятными.
Git 2.56 распознаёт распространённые ошибки в командах
Новая версия Git умеет выявлять некоторые типичные опечатки и ошибки синтаксиса и предлагает пользователю корректный вариант.
Например, Git может обратить внимание на ошибочную конструкцию:
git push origin/main
вместо:
git push origin main
А также на неправильное использование:
git branch --set-upstream-to origin main
вместо:
git branch --set-upstream-to=origin/main
Такие подсказки должны упростить работу с Git и сократить время на поиск причин ошибок в командах.
Что нового в Git 2.56
Таким образом, Git 2.56 стал заметным обновлением прежде всего для пользователей, работающих с большими репозиториями. Наиболее существенные изменения связаны с производительностью поиска общих предков, операциями reftable, git diff и созданием компактных pack-файлов.
Одновременно новая версия расширяет возможности управления историей и ветками: появились git add --resolved, git refs, git history drop, дополнительные возможности git bisect run, git replay и git branch --delete-merged.
Для разработчиков крупных проектов и серверных Git-инфраструктур улучшения Git 2.56 могут дать особенно заметный выигрыш в скорости и уменьшить объём хранимых данных.
