n1ro°
RU

Компьютеры · Инструкция

git commit-graph: ускорение истории большого Git-репозитория

git commit-graph особенно полезен в репозиториях с длинной историей и большим количеством веток, где команды.

Редакция N1RO · Проверено

Короткий ответ

git commit-graph хранит предвычисленную информацию о графе коммитов. Как записать, проверить и обслуживать commit-graph, включая split и changed-paths.

Что хранит commit-graph и почему Git может работать быстрее

Файл commit-graph содержит структурированную информацию о коммитах и их связях, чтобы Git не извлекал одни и те же данные заново из object database при каждом обходе истории. Он может хранить generation data и, при соответствующей записи, дополнительную информацию для changed-path Bloom filters. Практический эффект зависит от команды и структуры репозитория: ускорение заметнее там, где много ancestry‑проверок, merge-base, log и операций, которым нужно быстро исключать большие части графа. Сам commit-graph не меняет SHA коммитов и не редактирует ветки. Поэтому его можно рассматривать как производный индекс: если файл удалить или пересоздать, исходная история останется прежней. Это делает настройку подходящей для безопасного performance‑тюнинга, но всё равно полезно проверять файл штатной командой `verify`.

Совет: Сначала измерьте медленную команду до и после. Commit-graph полезен как оптимизация конкретной нагрузки, а не как ритуальная настройка любого маленького репозитория.

Как создать и проверить commit-graph

  1. Убедитесь, что вы работаете в локальном репозитории и нет необычных механизмов, несовместимых с commit-graph. Документация Git отдельно оговаривает ограничения, например replace objects/grafts могут отключать чтение или запись графа.
  2. Запустите `git commit-graph write --reachable`. Команда построит граф по коммитам, достижимым из refs. Для репозитория с обычным набором веток это понятная отправная точка.
  3. Проверьте структуру командой `git commit-graph verify`. Ненулевой exit code следует считать поводом пересоздать граф и проверить object database, а не игнорировать в automation.
  4. Повторите медленные операции — например `git log`, `git merge-base` или внутренние команды вашего инструмента — и измерьте эффект на той же файловой системе и после сопоставимого прогрева кеша.
  5. Если репозиторий постоянно получает новые коммиты и полная перезапись становится дорогой, рассмотрите `git commit-graph write --reachable --split`. Split chain позволяет добавлять слои и периодически объединять их по стратегии Git.

Важно: Commit-graph является производным файлом. Если сомневаетесь в его состоянии, безопаснее пересоздать его штатной командой, чем редактировать бинарный файл вручную.

Какой режим записи выбрать

  • write --reachable. Первичная простая настройка. Понятный полный граф достижимых коммитов
  • write --reachable --split. Очень большой, постоянно растущий repo. Инкрементальная цепочка слоёв
  • write --reachable --changed-paths. Нагрузки с path history. Добавляет Bloom filters для changed paths
  • verify. Контроль целостности commit-graph. Не заменяет fsck, но проверяет сам граф

Что даёт --changed-paths и почему он не нужен автоматически всем

Опция `--changed-paths` просит Git вычислить и сохранить Bloom filters, которые помогают некоторым history queries быстрее определять, мог ли коммит затрагивать интересующий путь. Выигрыш зависит от запросов. Если команда постоянно делает log по конкретным каталогам в огромной монорепе, дополнительные данные могут окупиться. Если нагрузка почти не использует path filtering, вы получите более дорогую запись и дополнительный объём без заметного эффекта. Поэтому включать changed-paths лучше после измерения. После обновления Git также стоит учитывать, что формат и алгоритмы обслуживания развиваются, а старые графы можно пересоздать. Commit-graph — кеш/индекс, а не артефакт, который нужно переносить между машинами как часть исходников проекта.

Предупреждение: Не коммитьте файлы commit-graph в рабочее дерево проекта. Они относятся к внутреннему состоянию `.git` и конкретной object database.

Как обслуживать split commit-graph в активно растущем репозитории

Split commit-graph хранит цепочку файлов, чтобы при каждом небольшом fetch не пересчитывать гигантский монолит с нуля. Новые слои добавляются поверх базовых, а Git умеет объединять их по правилам размера. Это удобно на серверах, зеркалах и больших developer clones, где refs постоянно двигаются. Но большее количество слоёв не означает бесконечное накопление: обслуживание должно позволять Git периодически compact/merge цепочку. Если ваша организация уже использует `git maintenance`, проверьте, не управляет ли commit-graph автоматизация за вас; дублирующие cron‑задачи могут зря создавать I/O. В CI с одноразовыми shallow clones построение графа обычно не окупается — job завершится раньше, чем индекс даст пользу в повторных операциях. Оптимизируйте persistent repositories, где история действительно используется много раз.

Когда commit-graph имеет смысл

  • Репозиторий большой по числу коммитов и веток, а не только по размеру бинарных файлов.
  • Медленны операции по ancestry/history, а не checkout из-за медленного диска.
  • Клон долгоживущий и commit-graph будет использоваться многократно.
  • Есть базовое измерение времени до оптимизации.
  • После записи `git commit-graph verify` проходит успешно.
  • Для changed-paths есть реальные path-based запросы, которые можно сравнить до/после.

Ограничения: replace objects, shallow clones и ожидания от ускорения

Commit-graph не универсально ускоряет любую операцию Git. Он не сделает быстрее передачу данных из сети, не уменьшит размер LFS‑объектов и не исправит медленный antivirus scan по рабочему дереву. Документация также указывает особенности совместимости с replace objects и grafts: такие механизмы могут приводить к отключению commit-graph, потому что они меняют представление истории. Shallow repositories имеют собственные ограничения полноты графа. Если после записи вы не видите выигрыша, проверьте, действительно ли bottleneck связан с обходом commit ancestry. Иногда более сильный эффект даст `git maintenance`, multi-pack-index, обновление Git или исправление процесса, который запускает тысячи одинаковых команд. Commit-graph полезен именно как точечный индекс для графа коммитов, а не как общий «ускоритель Git». Для команд с историей по путям отдельно учитывайте версию changed-path Bloom filters. В актуальной документации Git параметр `commitGraph.changedPathsVersion` управляет тем, какие версии фильтров читаются и записываются; более новые варианты могут быть несовместимы со старыми Git в смешанной среде. Поэтому на shared workstations и build-агентах сначала проверьте версии клиентов, а уже потом принудительно меняйте формат. Если такой совместимости не требуется, обычно достаточно поведения по умолчанию и периодической штатной перезаписи графа.

Что учитывать

Файл commit-graph содержит структурированную информацию о коммитах и их связях, чтобы Git не извлекал одни и те же данные заново из object database при каждом обходе истории. Он может хранить generation data и, при соответствующей записи, дополнительную информацию для changed-path Bloom filters. Практический эффект зависит от команды и структуры репозитория: ускорение заметнее там, где много ancestry‑проверок, merge-base, log и операций, которым нужно быстро исключать большие части графа. Сам…

Источники и проверка

Фактическая часть сверена по первичным источникам (в т.ч. git-commit-graph Documentation). Пример и формулировки — редакция N1RO на 2026-09-21.