Não pude usar a resposta mais popular porque a --batch-checkopção de linha de comando para o Git 1.8.3 (que eu tenho que usar) não aceita argumentos. As etapas a seguir foram tentadas no CentOS 6.5 com Bash 4.1.2
Conceitos chave
No Git, o termo blob implica o conteúdo de um arquivo. Observe que uma confirmação pode alterar o conteúdo de um arquivo ou nome de caminho. Portanto, o mesmo arquivo pode se referir a um blob diferente, dependendo da confirmação. Um determinado arquivo pode ser o maior na hierarquia de diretórios em um commit, enquanto não em outro. Portanto, a questão de encontrar confirmações grandes em vez de arquivos grandes coloca os assuntos na perspectiva correta.
Para o impaciente
O comando para imprimir a lista de blobs em ordem decrescente de tamanho é:
git cat-file --batch-check < <(git rev-list --all --objects | \
awk '{print $1}') | grep blob | sort -n -r -k 3
Saída de amostra:
3a51a45e12d4aedcad53d3a0d4cf42079c62958e blob 305971200
7c357f2c2a7b33f939f9b7125b155adbd7890be2 blob 289163620
Para remover esses blobs, use o BFG Repo Cleaner , conforme mencionado em outras respostas. Dado um arquivo blobs.txtque contém apenas os hashes de blob, por exemplo:
3a51a45e12d4aedcad53d3a0d4cf42079c62958e
7c357f2c2a7b33f939f9b7125b155adbd7890be2
Faz:
java -jar bfg.jar -bi blobs.txt <repo_dir>
A questão é encontrar os commits, o que é mais trabalhoso do que encontrar blobs. Para saber, por favor, continue lendo.
Trabalho adicional
Dado um hash de confirmação, um comando que imprime hashes de todos os objetos associados a ele, incluindo blobs, é:
git ls-tree -r --full-tree <commit_hash>
Portanto, se tivermos essas saídas disponíveis para todas as confirmações no repositório, com um hash de blob, o conjunto de confirmações será o que corresponderá a qualquer uma das saídas. Essa ideia está codificada no seguinte script:
#!/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
Se o conteúdo for salvo em um arquivo nomeado find-commits.sh, uma chamada típica será como em:
cat blobs.txt | find-commits.sh
Como anteriormente, o arquivo blobs.txtlista hashes de blob, um por linha. A create_db()função salva um cache de todas as listagens de confirmação em um subdiretório no diretório atual.
Algumas estatísticas dos meus experimentos em um sistema com dois processadores Intel (R) Xeon (E5) CPU E5-2620 2.00GHz apresentados pelo SO como 24 núcleos virtuais:
- Número total de confirmações no repositório = quase 11.000
- Velocidade de criação de arquivo = 126 arquivos / s. O script cria um único arquivo por confirmação. Isso ocorre apenas quando o cache está sendo criado pela primeira vez.
- Sobrecarga de criação de cache = 87 s.
- Velocidade média de pesquisa = 522 confirma / s. A otimização do cache resultou em uma redução de 80% no tempo de execução.
Observe que o script é de thread único. Portanto, apenas um núcleo seria usado por vez.