Como posso limpar minha pasta .git? Limpei o diretório do meu projeto, mas .git ainda é enorme

86

O .git / objects no diretório do meu projeto rails ainda é enorme, depois de excluir centenas de megabytes de lixo gerado acidentalmente.

Eu tentei git add -A, assim como outros comandos, atualizar o índice e remover arquivos inexistentes. Percebi, talvez incorretamente, que os arquivos com nomes de dois caracteres no diretório são blobs. Eu tentei voltar aos commits anteriores, mas sem sorte.

O que posso fazer para limpar este diretório?

24 lâmpadas
fonte

Respostas:

139
  • Se você adicionou os arquivos e depois os removeu, os blobs ainda existem, mas estão pendentes. git fsckirá listar blobs inacessíveis e git pruneirá excluí-los.

  • Se você adicionou os arquivos, confirmou-os e depois fez o rollback git reset --hard HEAD^, eles estão presos um pouco mais fundo. git fscknão listará nenhum commit ou blobs pendentes, porque o reflog do seu branch está segurando-os. Esta é uma maneira de garantir que apenas os objetos que estão em seu histórico permanecerão:

    git reflog expire --expire=now --all
    git repack -ad  # Remove dangling objects from packfiles
    git prune       # Remove dangling loose objects
    
  • Outra forma também é clonar o repositório, pois isso carregará apenas os objetos que são alcançáveis. No entanto, se os objetos pendentes foram compactados (e se você executou muitas operações, git pode muito bem ter compactado automaticamente), um clone local carregará todo o packfile:

    git clone foo bar                 # bad
    git clone --no-hardlinks foo bar  # also bad
    

    Você deve especificar um protocolo para forçar o git a computar um novo pacote:

    git clone file://foo bar  # good
    
Josh Lee
fonte
Sim, eu me comprometi antes de perceber o problema. Eu tentei de tudo, menos o último comando. Quando eu executo isso de dentro do diretório do meu projeto "aviso: você parece ter clonado um repositório vazio." Tenho lido a documentação, mas é um material pesado. Como posso apontar o clone para a fonte correta?
light24bulbs
1
@user O file://fooURL é relativo ao diretório atual e a file:///home/me/foo(três barras) é absoluto.
Josh Lee
obrigado! isso é cortado pela metade, mas minha embalagem ainda é dez vezes maior que o resto do repositório. Eu tentei podar ..
light24bulbs
1
@user Se muitos commits possuem arquivos grandes erroneamente, então você pode querer usar git-filter-branch para selecioná-los.
Josh Lee
2
Desculpe, sem efeito. Meu líder de desenvolvimento diz que o tamanho agora está dentro de uma faixa aceitável, mas desfavorável. Se você tiver tempo para continuar me alimentando com colher, isso seria excelente, mas você me colocou de volta no lugar. Obrigado jleedev.
lâmpadas 24 de
34

Você já tentou o git gccomando?

Ryanprayogo
fonte
3
git gc --aggressive --prunefunciona para mim. git gcnão. Talvez a configuração padrão não seja suficiente.
Moonlight Knight de
15

O Sparkleshare criou 13 GB de arquivos tmp_pack_ no meu git depois de falhar em puxar muitas vezes um enorme check-in de imagens. A única coisa que ajudou foi ...

rm -f .git/objects/*/tmp_*

'git gc' não removeu esses arquivos.

gato
fonte
Essa é uma solução de força bruta bastante, mas não vejo razão para não funcionar. Agradável!
light24bulbs de
1
Situações desesperadoras requerem medidas desesperadas, Funcionou como um encanto! Tks.
Medina
rm é para o comando linux? o que acontece com o usuário do Windows, em seguida, @cat?
gumuruh de
7

Se você ainda tem um grande repo após a poda e reembalagem ( gc --aggressive --prune=tomorrow...), então você pode simplesmente procurar o ímpar:

git rev-list --objects --all |
    while read sha1 fname
    do 
        echo -e "$(git cat-file -s $sha1)\t$\t$fname"
    done | sort -n

Isso lhe dará uma lista ordenada de objetos em tamanho crescente. Você pode usar git-filter-branch para remover o culpado do seu repo.

Consulte "Removendo objetos" em http://progit.org/book/ch9-7.html para obter orientação

ver
fonte
@DavidJames obrigado pela dica.
Tornei
Apenas no caso de alguém tropeçar nisso: há um erro de digitação no args entre parênteses: deveria ser --aggressive. Tentei editar, mas descobri que não é possível editar um erro de digitação tão pequeno.
hellobenallan
@hellobenallan, obrigado pela nota, corrigida
ver
1

Recursivamente:

find ./ -iname '*.!*' -size 0 -delete
for i in */.git; do ( echo $i; cd $i/..; git gc --aggressive --prune=now --force; ); done
Marcelo Grebois
fonte