Для лучшего восприятия прочитайте статью там, где она была первоначально опубликована: https://aymericbeaumet.com/faster-git-clones-with-sparse-checkouts.
Мы в REKKI работаем над монорепозиторием, содержащим весь бэкенд Go-код для большинства наших сервисов и заданий. С течением времени и ростом размера этого репозитория время, необходимое для первоначального клонирования, становится заметным. Хотя на рабочих станциях инженеров это не является проблемой, так как они работают без изменений, это влияет на системы без изменений, которые должны регулярно загружать кодовую базу: например, CI, CD или даже наш внутренний CLI.
Нашему CLI иногда требуется вытащить свежую версию определенного коммита из кодовой базы Go для выполнения бета-обновлений, когда наши инженеры просят об этом (например, для тестирования новых функций, которые еще не выпущены в стабильной версии). Клонировать монорепо Go каждый раз, когда они хотят установить бета-обновление, не вариант, так как это занимает больше минуты при хорошем соединении.
Неглубокое клонирование
Первый подход, который часто используется в подобных ситуациях, — это неглубокое клонирование. В то время как клон по умолчанию получает все коммиты и все объекты blob для отслеживаемой ветви (по умолчанию master
/main
), неглубокий клон получает объекты blob только для подмножества этих коммитов, что позволяет ускорить время клонирования.
Это очень распространено в мире CI. Например, и GitHub Actions, и Travis CI делают это по умолчанию.
Один из способов сделать неглубокое клонирование — указать флаг --depth=<n>
в команде git clone
, ограничив таким образом количество коммитов, которые будут извлечены, начиная с HEAD:
# fetch the latest commit
git clone --depth=1 git@github.com:rekki/go.git
Другой способ неглубокого клонирования — указать дату начала вместо количества коммитов. Это возможно с помощью флага --shallow-since=<date>
с абсолютной или относительной датой:
# fetch the last day of commits
git clone --shallow-since='1 day' git@github.com:rekki/go.git
Хотя неглубокие клоны хорошо работают в некоторых контекстах, они не справляются с задачей, загружая все объекты blob в рабочем дереве для заданных коммитов. Поэтому даже указание глубины в 1 приводит к тому, что для некоторых репозиториев время клонирования оказывается незначительным (в случае нашего Go monorepo это заняло 30 секунд).
Разреженные выгрузки
Еще один способ уменьшить количество загружаемых данных — использовать разреженные проверки. Разреженные проверки решают эту проблему, позволяя частично проверять рабочее дерево. В то время как неглубокие клоны дают вам контроль над коммитами, которые вы хотите получить, разреженные выгрузки позволят вам указать объекты blob, которые вы хотите получить.
Хотя разреженные выгрузки существуют с версии git 2.25.0, они всё ещё считаются экспериментальными. Маловероятно, что эта функция будет удалена в будущем, но могут произойти изменения как в ее реализации, так и в использовании.
Вы можете указать либо список каталогов (в так называемом режиме cone), либо список шаблонов (подобно .gitignore). Руководство рекомендует использовать режим конуса по соображениям производительности.
Использование разреженной проверки позволяет вам получать только те объекты blob, которые нужны для выполнения задачи. В нашем случае мы хотели клонировать только файлы, необходимые для создания нашего CLI. Вот как мы это сделали:
git clone --filter=blob:none --no-checkout git@github.com:rekki/go.git
cd go
git sparse-checkout set --cone go.mod go.sum cmd/rekki-cli pkg/rekki/errors
git checkout master
Давайте объясним шаг за шагом:
Вы можете легко адаптировать эти команды к своим условиям использования.
Такой подход позволил нам сократить время выполнения клона до менее чем 5 секунд. Мы довольны этим числом и знаем, что время будет расти пропорционально размеру кода, необходимого для создания CLI (и ничего больше). Поэтому в обозримом будущем оно должно оставаться быстрым.
Заключение
Использование разреженной проверки немного сложнее в плане команд, которые вам придется выполнять, но это позволяет лучше контролировать файлы, загружаемые в локальную файловую систему. Вам не всегда нужен весь репозиторий git, а разреженные проверки позволяют вам выбирать то, что вам нужно.
Попробуйте это в следующий раз, когда окажетесь в ситуации, когда git-клон занимает слишком много времени. А какой вариант использования есть у вас на примете? Оставьте комментарий со своими идеями ниже.