Git 2.54: новая history, хуки в конфиге и улучшения

Открытый проект Git выпустил версию Git 2.54 (а также 2.53), и GitHub разобрал ключевые изменения и новые возможности, появившиеся после релиза 2.52.

Одно из главных нововведений Git 2.54 — экспериментальная команда git history для упрощённого переписывания истории репозитория. Она предлагает два действия: reword и split и предназначена для типовых задач, когда нужно скорректировать уже сделанные коммиты без запуска интерактивного rebase.

git history reword <commit> открывает редактор с сообщением указанного коммита и переписывает его «на месте», обновляя все ветки, которые от него зависят. При этом не трогаются рабочее дерево и индекс, команда может работать даже в «голом» репозитории.

git history split <commit> позволяет интерактивно разделить один коммит на два: пользователь выбирает отдельные фрагменты (hunks), которые должны перейти в новый родительский коммит. Остальные изменения остаются в исходном коммите, а зависящие ветки переписываются с учётом новой структуры.

У команды есть ограничения: git history не работает с историями, содержащими merge-коммиты, и откажется от операции, если она приведёт к конфликту слияния. Инструмент рассчитан на локальные точечные изменения, а не на сложное переписывание истории, для которого по‑прежнему служит git rebase -i.

Новая команда опирается на внутренние механизмы git replay, которые были вынесены в отдельную библиотеку. За счёт этого history может работать без изменения рабочего дерева, что подходит как для интерактивной работы, так и для сценариев автоматизации.

Ещё одно заметное изменение — новый способ задания Git hooks через конфигурационные файлы. Раньше хуки нужно было хранить как исполнимые скрипты в .git/hooks (или в каталоге, указанном core.hooksPath), что усложняло их переиспользование между репозиториями.

Теперь можно описывать хуки в конфигурации с помощью ключей hook.<name>.command и hook.<name>.event. Такие настройки могут находиться в пользовательском ~/.gitconfig, системном /etc/gitconfig или локальном конфиге репозитория, что упрощает централизованное подключение правил.

Git также научился запускать несколько хуков на одно и то же событие. Например, перед коммитом можно по отдельности настроить запуск линтера и сканера секретов. Конфигурации будут выполняться по порядку, а традиционный скрипт в $GIT_DIR/hooks, если он есть, отработает последним.

Список активных хуков и источник их определения теперь можно посмотреть командой git hook list. При этом любой хук допускается временно отключить без удаления конфигурации, установив для него hook.<name>.enabled = false, что полезно, когда правило задано на системном уровне, а конкретному репозиторию оно не нужно.

В рамках этих изменений была обновлена внутренняя логика вызова хуков. Ряд встроенных хуков (например, pre-push, post-rewrite и receive-pack) перевели на использование нового API, чтобы они также работали через конфигурационный механизм.

Начиная с Git 2.54, стратегия geometric для обслуживания репозитория через git maintenance становится стратегией по умолчанию для ручного запуска. Ранее она была доступна по опции maintenance.strategy и требовала явного включения.

Геометрическая стратегия анализирует набор pack-файлов и ищет возможность объединить их так, чтобы число объектов образовывало геометрическую прогрессию. В этом случае выполняется «геометрическая перепаковка» без полной сборки мусора; к полноценному gc Git переходит только тогда, когда можно объединить всё содержимое в один pack.

На практике это даёт более эффективное обслуживание репозиториев «из коробки». Вместо ресурсоёмкого all-into-one repack Git постепенно объединяет пакеты и параллельно поддерживает в актуальном состоянии commit-graph, reflog и другие вспомогательные структуры.

Если ранее уже была настроена maintenance.strategy = geometric, поведение не меняется. Те, кто полагался на стандартный gc без явной стратегии, теперь автоматически получат преимущества геометрической перепаковки. При необходимости можно вернуться к прежнему подходу, установив maintenance.strategy = gc.

В новой версии обновился инструмент git add -p, который используют для интерактивного стейджинга отдельных фрагментов. При переходе между hunks клавишами J и K теперь отображается, был ли каждый из них ранее принят или пропущен, что снижает риск ошибок при выборке.

Флаг –no-auto-advance изменяет поведение на границе файлов: по умолчанию после решения по каждому фрагменту в файле сессия переходит к следующему файлу автоматически, а с этой опцией остаётся на текущем. Далее можно самостоятельно перемещаться между файлами с помощью < и > для комплексного пересмотра решений перед коммитом.

Экспериментальная команда git replay, которая переносит коммиты на новую базу без изменения рабочего дерева, получила несколько важных обновлений. Теперь по умолчанию выполняются атомарные обновления ссылок (вместо вывода команд update-ref на stdout), появилась опция –revert для обратного применения диапазона коммитов, добавлена возможность пропускать опустевшие коммиты и поддерживается работа вплоть до корневого коммита.

HTTP‑транспорт Git научился корректно обрабатывать код HTTP 429 «Too Many Requests». Раньше это считалось фатальной ошибкой, теперь клиент может повторить запрос, используя заголовок Retry-After, если он есть, либо применяя задержку, заданную в новой настройке http.retryAfter.

Дополнительно появились параметры http.maxRetries и http.maxRetryTime, которые позволяют контролировать количество попыток и максимальное время ожидания. Это особенно полезно при работе с серверами, ограничивающими нагрузку.

Команда git log -L, которая отслеживает историю определённого диапазона строк в файле, была переориентирована на использование стандартного diff‑конвейера Git. Ранее она применяла отдельный путь обработки, из‑за чего не работала с частью опций, в том числе с -S и -G (поиск по содержимому изменений).

Теперь вывод git log -L проходит через привычный diff‑механизм, поддерживает форматирование патчей и совместим с «pickaxe»‑поиском. Это даёт возможность, например, проследить историю функции и одновременно отфильтровать коммиты по наличию изменений определённого символа или текста внутри неё.

Многослойные incremental multi-pack indexes (MIDX), обсуждавшиеся ранее для версий 2.47 и 2.50, получили поддержку компакции. Git может объединять меньшие MIDX‑уровни и связанные с ними битовые карты достижимости, чтобы ограничить рост числа слоёв в цепочке.

Компакция делает incremental MIDX более применимой для долгоживущих репозиториев, где со временем накапливается большое количество слоёв и требуется удерживать структуру в управляемом виде.

Команда git status обзавелась конфигурацией status.compareBranches. По умолчанию она показывает, насколько текущая ветка опережает или отстаёт от настроенного upstream‑репозитория (например, «Ваша ветка опережает ‘origin/main’ на 3 коммита»).

С помощью status.compareBranches можно попросить Git одновременно сравнивать ветку и с удалённым репозиторием, куда идут push‑ы, или с обоими источниками. Это удобно, если upstream и push‑цель различаются, как в типичных сценариях с форками, когда fetch идёт с одного remote, а push — в другой.

В Git 2.54 команда git rebase получила опцию –trailer, которая добавляет указанный трейлер к каждому перебазируемому коммиту через механизм interpret-trailers. Раньше для этого приходилось конструировать сложную команду с -x и git commit –amend, теперь достаточно одного флага rebase –trailer.

Это упрощает массовое добавление подписи вида Reviewed-by: или других служебных строк к серии коммитов, не требуя ручного редактирования каждого сообщения.

При проверке подписей Git скорректировал отображение случаев, когда коммит был подписан действительной GPG‑подписью, но ключ впоследствии истёк. Такие подписи раньше показывались красным цветом и могли восприниматься как некорректные, теперь Git трактует их как «хорошие» подписи, что точнее отражает фактическую валидность на момент создания коммита.

Команда git blame получила опцию –diff-algorithm, которая позволяет выбирать алгоритм сравнения (histogram, patience, minimal и др.) при вычислении авторства строк. В зависимости от характера изменений в истории это может заметно влиять на удобство и точность результата blame.

Существенные изменения произошли во внутренних механизмах работы с базой объектов (ODB). API источников объектов было переработано под модульную архитектуру с подключаемыми бэкэндами: функции вроде read_object(), write_object() и for_each_object() теперь вызываются через указатели на функции для каждого источника.

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

Экспериментальная команда git backfill для докачки отсутствующих blob‑объектов в частичных клонах научилась принимать аргументы ревизий и pathspec. Ранее backfill всегда загружал объекты, достижимые из HEAD по всему дереву.

Теперь можно ограничить докачку конкретным диапазоном истории (например, main~100..main) или набором путей (например, git backfill — ‘*.c’), включая pathspec с подстановочными символами. Это делает backfill более практичным для крупных частичных клонов, где нужны лишь определённые участки истории.

В конфигурации alias снято ограничение на использование только ASCII‑символов и дефиса в именах алиасов. Благодаря новой синтаксической форме под‑разделов стало возможным создавать алиасы с любыми символами (кроме перевода строки и NUL‑байта), например, на шведском или японском.

Классический формат [alias] co = checkout по‑прежнему поддерживается для ASCII‑имён. В новом формате имя алиаса интерпретируется как последовательность байтов с учётом регистра, а определение команды задаётся через ключ command. Кроме того, обновлена поддержка автодополнения в оболочке для таких алиасов.

Алгоритм diff histogram получил исправление, касающееся качества итогового вывода. После выполнения любого алгоритма Git выполняет «компакцию», смещая и объединяя группы изменений для более чистого патча. Иногда это приводило к тому, что группа сдвигалась через «якорные» строки, выбранные histogram, и создавался визуально избыточный diff.

Теперь Git отслеживает такие случаи, повторно дифференцирует затронутые участки и формирует более компактный вывод, который лучше соответствует тому, что ожидает увидеть разработчик.

В конце GitHub напоминает, что перечисленные изменения — это лишь часть нововведений релизов 2.53 и 2.54. За полным списком улучшений и исправлений предлагается обращаться к официальным release notes соответствующих версий в репозитории Git. Автор обзора — Тейлор Блау (Taylor Blau), Principal Software Engineer в GitHub, который работает над Git.

Источник: блог GitHub и заметки к релизам Git 2.53 и Git 2.54.

Читать новости ИИ и технологий в Telegram.


Оцените статью
Gimal-Ai