Чистим Git-репозиторий

Внезапно после множества правок, попавших на сайт после перехода на Hakyll, размер Git-репозитория оказался равным 80 Мб. Конечно, некоторую часть из этого занимают фотографии, но огромное количество занятого пространства приходится на старые удалённые файлы. В общем, идея всё почистить давно поселилась в моей голове. Теперь это время настало.

Для этой операции воспользуемся утилитой BFG Repo Cleaner.

Итак, извлекаем новую копию репозитория.

git clone --mirror git@github.com:dikmax/dikmax.name.git

Удаляем из истории всё, что больше 64 Кб.

java -jar bfg.jar --strip-blobs-bigger-than 64K dikmax.name.git

Эта утилита переписывает историю, но ничего на самом деле не удаляет. Убрать не привязанные, то есть лишние, объекты можно с помощью следующих команд.

cd dikmax.name.git
git reflog expire --expire=now --all
git gc --prune=now --aggressive

Теперь размер репозитория уменьшился в два раза, до 39 Мб, что чуть больше размера всех имеющихся на сайте фотографий.

Заливаем изменения на GitHub:

git push --force

А теперь то, что оказалось важным, но в инструкции отсутствует. После этой операции HEAD будет указывать на тот же коммит, что и раньше, а это значит, что возможно выполнить git push в любой ранее извлечённой копии. Эта команда выполнится безо всяких предупреждений и зальёт разницу, то есть как раз все те файлы которые мы благополучно из репозитория выпилили. Более того, так как и порезанные коммиты из репозитория никуда не исчезнут, то получится что у нас будет храниться две версии для каждого старого коммита: полная и порезанная. Поэтому, если в репозиторий могут добавлять изменения несколько человек, то все они должны быть предупреждены и действия должны быть согласованными. В моем же случае git push выполнял автоматически скрипт синхронизации комментариев с Disqus, что сводило все усилия сделать всё как надо к нулю.

Предыдущий абзац одним предложением: абсолютно все рабочие копии должны быть извлечены заново.