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?

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
    

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


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.


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


@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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.