Освоение сборки мусора в Git для максимальной производительности
Узнайте, когда запускать git gc, что он очищает и как избежать рискованной агрессивной очистки на активных репозиториях.
Освоение сборки мусора в Git для максимальной производительности
Сборка мусора в Git предотвращает бесконечное накопление рыхлых объектов, устаревших недостижимых коммитов и неэффективных пакетных файлов в вашем репозитории. Если ваш репозиторий работает медленно, занимает слишком много дискового пространства или в нём было много перебазирований и очисток веток, git gc — один из первых инструментов обслуживания, который стоит освоить.
Обычно вам не нужно запускать его каждый день. Git выполняет автоматическое обслуживание во время обычных команд при достижении определённых порогов. Тем не менее, понимание того, что он делает, помогает избежать двух распространённых ошибок: игнорирование раздутого репозитория в течение месяцев или запуск агрессивной очистки на общем репозитории без понимания последствий.
Что делает сборка мусора в Git
Git хранит данные как объекты: коммиты, деревья, блобы и теги. Новые объекты могут начинаться как рыхлые файлы в .git/objects/. Со временем Git может упаковать множество объектов вместе в компактные пакетные файлы. Упакованные объекты используют диск более эффективно и обычно быстрее сканируются Git.
git gc выполняет несколько задач обслуживания, включая:
- Упаковку рыхлых объектов в пакетные файлы.
- Объединение существующих пакетных файлов, когда это полезно.
- Удаление недостижимых объектов, которые достаточно стары для удаления.
- Очистку временных файлов, оставшихся от прерванных операций.
- Обновление вспомогательных данных, таких как файлы commit-graph в современных настройках Git, если это настроено.
Недостижимое не всегда означает безопасное для немедленного удаления. Коммит может стать недостижимым после перебазирования, изменения, сброса или удаления ветки. Git обычно сохраняет недавно недостижимые объекты в течение льготного периода, чтобы у вас было время восстановить их с помощью git reflog.
Проверьте размер репозитория перед очисткой
Начните с измерения репозитория, а не с догадок:
git count-objects -vH
Полезные поля включают count, size, in-pack, packs и size-pack. Большое количество рыхлых объектов может замедлить повседневные операции Git. Большой size-pack может просто означать, что репозиторий содержит много реальной истории, большие бинарные файлы или ресурсы поставщика.
Чтобы проверить использование диска напрямую, выполните:
du -sh .git
Если .git огромен из-за того, что кто-то закоммитил артефакты сборки или большие архивы, одной сборки мусора может быть недостаточно для решения реальной проблемы. Возможно, вам потребуется удалить большие файлы из будущих коммитов, переместить их в Git LFS или переписать историю с помощью такого инструмента, как git filter-repo, после согласования с командой.
Запустите обычную сборку мусора
Для рутинной очистки используйте:
git gc
Это безопасный вариант по умолчанию. Он позволяет Git решить, какую работу по обслуживанию стоит выполнять, и соблюдает обычные правила удаления.
Вы можете попросить Git выполнить автоматическое обслуживание только в том случае, если пороговые значения говорят, что это необходимо:
git gc --auto
Большинству пользователей не нужно вызывать --auto вручную, потому что Git уже делает это за кулисами. Тем не менее, это полезно в скриптах, где вы хотите выполнить лёгкую очистку без принудительной полной переупаковки каждый раз.
Если вы хотите удалить старые недостижимые объекты, используя стандартный льготный период, выполните:
git gc --prune=now
Используйте --prune=now осторожно. Он может удалить точки восстановления, которые git reflog мог бы помочь найти. Избегайте его сразу после сложного перебазирования, удаления ветки или сброса, если вы не уверены, что старые объекты вам не нужны.
Будьте осторожны с --aggressive
git gc --aggressive указывает Git потратить больше времени процессора на попытку оптимизировать упаковку объектов:
git gc --aggressive
Это не волшебная кнопка ускорения. Во многих репозиториях дополнительная работа даёт мало пользы по сравнению с обычным git gc и может занять много времени на больших историях. Используйте его только тогда, когда вы измерили реальную проблему с размером репозитория или производительностью и можете позволить себе окно обслуживания.
Для повседневной работы предпочитайте обычный git gc. Если ваш репозиторий регулярно требует агрессивной очистки, более глубокая проблема часто заключается в больших файлах, сгенерированных артефактах или рабочем процессе, который создаёт много недостижимой истории.
Используйте современное обслуживание Git для постоянного ухода
Последние версии Git включают git maintenance, который может планировать фоновые задачи, такие как предварительная выборка, обновление commit-graph и инкрементальная переупаковка, в зависимости от вашей платформы и конфигурации.
Чтобы запустить обслуживание один раз:
git maintenance run
Чтобы включить запланированное обслуживание для вашей учётной записи пользователя:
git maintenance start
Проверьте версию Git и локальную документацию, прежде чем полагаться на запланированное обслуживание в автоматизации, потому что точная интеграция планировщика различается в зависимости от операционной системы и сборки Git.
Практический рабочий процесс очистки
Безопасный процесс очистки для локального репозитория выглядит так:
git status
git count-objects -vH
git gc
git count-objects -vH
Убедитесь, что ваше рабочее дерево чисто перед обслуживанием. Git может запускать сборку мусора при наличии локальных изменений, но чистое дерево устраняет сомнения, если вам нужно будет устранять неполадки после.
Для общего голого репозитория на сервере планируйте обслуживание в период низкой активности. Избегайте тяжёлых переупаковок во время пиковой активности CI, потому что операции клонирования, получения и отправки могут конкурировать за диск и процессор.
Когда сборка мусора не поможет
Сборка мусора не может исправить каждый медленный репозиторий Git. Она не удалит файлы, которые всё ещё достижимы в истории. Она не сделает монорепозиторий маленьким, если активная история действительно содержит годы больших ресурсов. Она не восстановит повреждённый репозиторий сама по себе.
Если производительность всё ещё плоха после обычной очистки, ищите эти причины:
- Большие бинарные файлы, закоммиченные напрямую в Git.
- Слишком много сгенерированных файлов, отслеживаемых в репозитории.
- Антивирус или индексация файловой системы, сканирующие
.gitпри каждой операции. - Медленное сетевое хранилище, на котором находится рабочее дерево.
- Очень большие рабочие деревья, где может помочь разрежённая проверка.
Используйте git gc как обслуживание, а не как замену гигиене репозитория. Запускайте обычную очистку, когда количество объектов растёт, избегайте агрессивной очистки, если вы не измерили необходимость, и относитесь к большим отслеживаемым артефактам как к проблеме рабочего процесса, которую нужно исправить в источнике.