Чтобы найти самые большие файлы, хранящиеся в достижимой истории Git репозитория на macOS, откройте Терминал, перейдите в репозиторий и передайте список объектов Git через конвейер в git cat-file и sort. Это выведет несжатый размер каждого блоба (blob) в байтах и подсказку пути к файлу. Таким образом можно обнаружить файлы, которые были удалены или заменены, но остались в коммитах, достижимых из веток или тегов.
Запуск сканирования истории из Терминала
В Терминале используйте команду cd, чтобы перейти в репозиторий. Заключите путь к папке в кавычки, если он содержит пробелы. Затем выполните:
git rev-list --objects --all |
git cat-file --batch-check='%(objecttype) %(objectsize) %(objectname) %(rest)' |
awk '$1 == "blob"' |
sort -k2,2nr |
head -20
Результат будет отсортирован по убыванию размера. В каждой строке отображается тип объекта, размер в байтах, идентификатор объекта (object ID) и, если Git предоставляет эти данные, подсказка пути. Команда git rev-list --objects --all обходит объекты, на которые ссылаются коммиты, достижимые из ссылок (refs), таких как локальные ветки и теги; git cat-file --batch-check сообщает тип и размер каждого объекта. Конвейер фильтрует только блобы — объекты, хранящие содержимое файлов. В документации Git по rev-list описан обход объектов и их именование, а в документации по cat-file описан пакетный вывод размера и типа.
Команда sort -k2,2nr использует встроенную в macOS утилиту sort для численной сортировки в обратном порядке по второму полю, разделенному пробелами (размеру в байтах). Команда head -20 ограничивает вывод 20 строками; измените число или удалите эту последнюю строку, чтобы увидеть больше. Команда только считывает данные репозитория. Она не изменяет коммиты или файлы.
Внимательно интерпретируйте результаты
Строка идентифицирует объект-блог (blob), а не обязательно файл, присутствующий в рабочем дереве в данный момент. Большой объект может относиться к старой версии файла, а подсказка пути не является полным историческим индексом путей: в документации Git указано, что при использовании --objects имена являются лишь подсказками, могут быть изменены из-за символов перевода строки, и если у объекта есть несколько имен, может отображаться только одно из них. Рассматривайте указанный путь как зацепку, а затем проверяйте соответствующие коммиты, чтобы подтвердить, когда и где появилось это содержимое. В примечаниях Git к именам объектов в rev-list объясняются эти ограничения.
Это сканирование охватывает объекты, достижимые из ссылок, найденных с помощью --all, а не каждый объект, который физически может оставаться в базе данных объектов. Чтобы проверить локальное хранилище объектов, включая недостижимые объекты, выполните:
git cat-file --batch-all-objects \
--batch-check='%(objecttype) %(objectsize) %(objectname)' |
awk '$1 == "blob"' |
sort -k2,2nr |
head -20
Параметр --batch-all-objects обходит все объекты в репозитории и альтернативных хранилищах объектов, включая объекты, недостижимые из ссылок. Эта вторая команда опускает пути к файлам, поэтому для дальнейшего исследования используйте идентификатор объекта (object ID). В документации по cat-file отмечается как более широкий охват объектов, так и то, что каждый объект отображается один раз, даже если он сохранен несколько раз.
Размер блоба не равен занимаемому месту на диске
Выводимый параметр objectsize — это несжатый размер объекта Git. Git может сжимать объекты или сохранять их в виде дельт (разностей) внутри pack-файлов, поэтому большой блоб не обязательно занимает именно такой объем дискового пространства. Для общего обзора использования хранилища выполните git count-objects -vH; его поле size-pack сообщает размер упакованных данных, а остальные поля обобщают информацию о свободных (loose) объектах и связанном хранилище. Эти показатели описаны в руководстве Git по count-objects. Чтобы проверить размеры упакованных объектов и сведения о дельтах, команда git verify-pack -v выводит список размеров каждого упакованного объекта и его размер в pack-файле, но для этого требуется соответствующий файл .idx. Этот вывод определен в руководстве по verify-pack.
Если вы обнаружили большой файл в истории
Сначала определите, в чем заключается ваша задача: понять текущее состояние рабочей копии (checkout) или уменьшить историю репозитория. Если вас интересует только текущая версия, проверьте файлы в Finder или используйте вывод списка файлов с размерами в Терминале; сканирование истории решает другую задачу, выполняя поиск по достижимым объектам Git.
Если большой файл необходимо удалить из всех ревизий, простого удаления в новом коммите недостаточно — старые копии останутся в истории. Перезапись истории меняет идентификаторы коммитов и затрагивает других пользователей репозитория, поэтому согласуйте свои действия перед выполнением и сохраните резервную копию. Проект git-filter-repo предлагает режим анализа только для чтения, git filter-repo --analyze, который создает отчеты, помогающие решить, что именно следует отфильтровать; в режиме анализа он не выполняет перезапись. В документации проекта описана опция анализа и содержится предупреждение о том, что фильтрация приводит к перезаписи истории.
Первый конвейер команд — это практичная отправная точка, когда цель состоит в том, чтобы найти самое большое содержимое файлов в истории локального репозитория. Используйте сканирование всех объектов, когда значение имеют недостижимые остаточные данные, и сопоставляйте размеры объектов Git с данными о pack-хранилище, прежде чем связывать использование дискового пространства с конкретным блобом.
Источники
git-filter-repo — GitHub