Я не смог использовать самый популярный ответ, потому что --batch-check переключатель командной строки для Git 1.8.3 (который я должен использовать) не принимает никаких аргументов. Последующие шаги были опробованы на CentOS 6.5 с Bash 4.1.2
Ключевые идеи
В Git термин blob подразумевает содержимое файла. Обратите внимание, что фиксация может изменить содержимое файла или пути. Таким образом, один и тот же файл может ссылаться на другой BLOB-объект в зависимости от фиксации. Определенный файл может быть самым большим в иерархии каталогов в одном коммите, а не в другом. Поэтому вопрос поиска больших коммитов вместо больших файлов ставит вопросы в правильном ракурсе.
Для нетерпеливых
Команда для печати списка больших двоичных объектов в порядке убывания размера:
git cat-file --batch-check < <(git rev-list --all --objects | \
awk '{print $1}') | grep blob | sort -n -r -k 3
Пример вывода:
3a51a45e12d4aedcad53d3a0d4cf42079c62958e blob 305971200
7c357f2c2a7b33f939f9b7125b155adbd7890be2 blob 289163620
Чтобы удалить такие капли, используйте BFG Repo Cleaner , как указано в других ответах. Имеется файл, blobs.txtкоторый содержит только хэши больших двоичных объектов, например:
3a51a45e12d4aedcad53d3a0d4cf42079c62958e
7c357f2c2a7b33f939f9b7125b155adbd7890be2
Делать:
java -jar bfg.jar -bi blobs.txt <repo_dir>
Вопрос в том, чтобы найти коммиты, а это больше работы, чем поиск блобов. Чтобы узнать, пожалуйста, читайте дальше.
Дальнейшая работа
С учетом хэша коммита команда, которая печатает хэши всех объектов, связанных с ним, включая большие двоичные объекты:
git ls-tree -r --full-tree <commit_hash>
Таким образом, если у нас есть такие выходные данные, доступные для всех коммитов в репо, то с учетом хэша большого двоичного фрагмента, те коммиты, которые соответствуют любому из выходных данных. Эта идея закодирована в следующем сценарии:
#!/bin/bash
DB_DIR='trees-db'
find_commit() {
cd ${DB_DIR}
for f in *; do
if grep -q $1 ${f}; then
echo ${f}
fi
done
cd - > /dev/null
}
create_db() {
local tfile='/tmp/commits.txt'
mkdir -p ${DB_DIR} && cd ${DB_DIR}
git rev-list --all > ${tfile}
while read commit_hash; do
if [[ ! -e ${commit_hash} ]]; then
git ls-tree -r --full-tree ${commit_hash} > ${commit_hash}
fi
done < ${tfile}
cd - > /dev/null
rm -f ${tfile}
}
create_db
while read id; do
find_commit ${id};
done
Если содержимое сохранено в файле с именем, find-commits.shтипичный вызов будет выглядеть так:
cat blobs.txt | find-commits.sh
Как и ранее, в файле blobs.txtперечислены хэши BLOB-объектов, по одному на строку. create_db()Функция сохраняет кэш всех фиксации списков в подкаталог в текущем каталоге.
Немного статистики из моих экспериментов на системе с двумя процессорами Intel (R) Xeon (R) CPU E5-2620 2,00 ГГц, представленной ОС как 24 виртуальных ядра:
- Общее количество коммитов в репо = почти 11 000
- Скорость создания файла = 126 файлов / с. Сценарий создает один файл на коммит. Это происходит только тогда, когда кэш создается впервые.
- Затраты на создание кэша = 87 с.
- Средняя скорость поиска = 522 коммитов / с. Оптимизация кэша привела к сокращению времени выполнения на 80%.
Обратите внимание, что скрипт является однопоточным. Следовательно, только одно ядро будет использоваться одновременно.