Ускорение Git: основные методы оптимизации производительности
Ускорьте Git за счет уменьшения затрат на клонирование, разумного использования Git LFS, удаления устаревших ссылок, игнорирования сгенерированных файлов и применения разреженного checkout.
Ускорение Git: основные методы оптимизации производительности
Медленный Git обычно имеет конкретную причину: слишком много истории, слишком много неотслеживаемых файлов, большие бинарные объекты, дорогие сканирования файловой системы или задержки в сети. Прежде чем винить сам Git, проверьте, какая операция медленная и что она пытается прочитать или загрузить.
Оптимизация производительности Git работает лучше всего, когда вы подбираете исправление под симптом. Медленный CI-клон требует другого решения, чем медленный git status в огромном рабочем дереве.
Понимание причин медленной производительности Git
Начните с распространенных причин:
- Длинная история с множеством файлов и ссылок.
- Большие бинарные файлы, зафиксированные напрямую в Git.
- Результаты сборки, папки зависимостей или логи, оставленные без игнорирования в рабочем дереве.
- Множество устаревших удаленных веток и тегов.
- Медленные сетевые соединения с удаленным репозиторием.
- Старые версии Git, в которых отсутствуют новые улучшения обслуживания и разреженного checkout.
Выполняйте медленную команду осознанно. Если git clone медленный, смотрите на размер истории и сетевую передачу. Если git status медленный, смотрите на размер рабочего дерева, игнорируемые файлы и поведение файловой системы. Если git fetch медленный, смотрите на удаленные ссылки, теги и измененные объекты.
Снижение затрат на клонирование и fetch
Для CI, задач развертывания и проверки только для чтения вам часто не нужна полная история.
Используйте поверхностный клон:
git clone --depth <число> <url_репозитория>
Например, чтобы клонировать только последние 10 коммитов:
git clone --depth 10 https://github.com/example/repo.git
Для CI-задач, которые собирают только текущий коммит, --depth 1 часто достаточно. Для работы разработчика полный клон обычно менее удивителен, потому что такие команды, как глубокий git log, checkout старых тегов и некоторые rebase, требуют больше истории.
Если у вас уже есть поверхностный клон и вам нужно больше истории, углубите его:
git fetch --deepen=50 origin
Или преобразуйте его в полный клон:
git fetch --unshallow origin
Для частичных потребностей в данных более новые версии Git также поддерживают фильтры частичного клонирования, такие как --filter=blob:none, но используйте их только тогда, когда ваш Git-хост и рабочий процесс хорошо их поддерживают:
git clone --filter=blob:none https://github.com/example/large-repo.git
Держите большие файлы вне обычной истории Git
Большие бинарники — один из самых быстрых способов сделать Git медленным. Изображения, видео, архивы, дизайнерские файлы и файлы моделей часто плохо сжимаются или не поддаются сравнению.
Используйте Git LFS для больших ресурсов, которые действительно должны быть в репозитории:
git lfs install
git lfs track "*.psd"
git lfs track "assets/*.mp4"
git add .gitattributes
git commit -m "Отслеживать большие ресурсы с помощью Git LFS"
Git LFS влияет на будущие коммиты после применения правил отслеживания. Если кто-то уже зафиксировал большие файлы в обычной истории Git, удаления их из текущего дерева недостаточно. Возможно, потребуется согласованная перезапись истории с помощью такого инструмента, как git lfs migrate import или git filter-repo.
Для сгенерированных артефактов сборки лучшим ответом обычно является не LFS. Не фиксируйте их. Вместо этого добавьте их в .gitignore:
node_modules/
dist/
coverage/
*.log
Очистка локальных ссылок и объектов
Устаревшие удаленные ветки добавляют мусор и могут замедлять команды, которые выводят список или проверяют ссылки. Удаляйте их во время fetch:
git fetch --prune
Удалите локальные ветки, которые уже слиты и больше не нужны:
git branch --merged
git branch -d old-feature-branch
Позвольте Git выполнить обслуживание:
git maintenance run
В старых рабочих процессах git gc все еще полезен:
git gc
Избегайте агрессивных команд очистки, если вы не знаете, зачем они вам нужны. Например, истечение reflog может затруднить восстановление после неудачного сброса.
Удешевление git status
git status должен проверять рабочее дерево. Если ваш каталог проекта содержит тысячи сгенерированных файлов или файлов зависимостей, статус может стать шумным и медленным.
Используйте .gitignore для файлов, которые Git не должен учитывать. Если файл уже отслеживается, .gitignore не остановит Git от его отслеживания; вы должны сначала удалить его из индекса:
git rm --cached path/to/generated-file
Для очень больших репозиториев, где вам нужна только часть дерева, может помочь разреженный checkout:
git sparse-checkout init --cone
git sparse-checkout set services/api docs
Это оставляет в вашем рабочем дереве только выбранные пути. Это полезно в монорепозиториях, но ваша команда должна документировать ожидаемые разреженные пути, чтобы разработчики не пропустили нужные им файлы.
Разделение fetch и интеграции
git pull выполняет fetch, а затем интегрирует изменения с помощью merge или rebase, в зависимости от конфигурации. Когда репозиторий большой или ветка разошлась, часто понятнее сначала выполнить fetch:
git fetch origin
git log --oneline HEAD..origin/main
git merge origin/main
Это само по себе не уменьшает сетевую передачу. Это дает вам контроль перед изменением вашей рабочей ветки.
Практический вывод
Используйте поверхностные клоны для краткосрочных задач, Git LFS для больших ресурсов, .gitignore для сгенерированных файлов, удаление для устаревших ссылок и разреженный checkout для больших деревьев, где вам нужна только часть. Держите Git актуальным, но не используйте такие инструменты целостности, как git fsck, в качестве исправления производительности, если вы не подозреваете повреждение репозитория.
Когда Git работает медленно, запишите точную команду и то, куда уходит время: сетевая передача, обработка объектов или сканирование рабочего дерева. Эта одна деталь обычно указывает на правильную оптимизацию.