Como remover objects não utilizados de um repository git?

Eu acidentalmente adicionado, comprometido e empurrado um arquivo binário enorme com o meu último compromisso para um repository Git.

Como posso fazer com que o Git remova o (s) object (s) que foi / foram criado (s) para esse commit, assim meu diretório .git encolherá novamente para um tamanho sano?

Edit : Obrigado por suas respostas; Eu tentei várias soluções. Nenhum funcionou. Por exemplo, o do GitHub removeu os arquivos do histórico, mas o tamanho do diretório .git não diminuiu:

 $ BADFILES=$(find test_data -type f -exec echo -n "'{}' " \;) $ git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch $BADFILES" HEAD Rewrite 14ed3f41474f0a2f624a440e5a106c2768edb67b (66/66) rm 'test_data/images/001.jpg' [...snip...] rm 'test_data/images/281.jpg' Ref 'refs/heads/master' was rewritten $ git log -p # looks nice $ rm -rf .git/refs/original/ $ git reflog expire --all $ git gc --aggressive --prune Counting objects: 625, done. Delta compression using up to 2 threads. Compressing objects: 100% (598/598), done. Writing objects: 100% (625/625), done. Total 625 (delta 351), reused 0 (delta 0) $ du -hs .git 174M .git $ # still 175 MB :-( 

Eu respondi isso em outro lugar, e vou copiar aqui desde que eu tenho orgulho disso!

… e sem mais delongas, posso apresentar a você este script útil, git-gc-all, garantido para remover todo o seu lixo do git até que eles possam vir com variables ​​de configuração extras:

 git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 \ -c gc.rerereresolved=0 -c gc.rerereunresolved=0 \ -c gc.pruneExpire=now gc "$@" 

A opção –agressiva pode ser útil.

OBSERVAÇÃO: isso removerá TODAS as coisinhas não referenciadas, então não venha chorar para mim se decidir mais tarde que queria manter algumas delas!

Você também pode precisar executar algo como estes primeiro, oh querida, git é complicado !!

 git remote rm origin rm -rf .git/refs/original/ .git/refs/remotes/ .git/*_HEAD .git/logs/ git for-each-ref --format="%(refname)" refs/original/ | xargs -n1 --no-run-if-empty git update-ref -d 

Eu coloquei tudo isso em um script, aqui:

http://sam.nipl.net/b/git-gc-all-ferocious

Seu git reflog expire --all está incorreto. Ele remove as inputs de reflog que são mais antigas que o tempo de expiração, cujo padrão é 90 dias. Use git reflog expire --all --expire=now .

Minha resposta a uma pergunta semelhante lida com o problema de realmente remover objects não usados ​​de um repository.

1) Remova o arquivo do repository do git (e não o sistema de arquivos):

  • git rm --cached path/to/file

2) Encolher o repo usando:

  • git gc ,

  • ou git gc --aggressive

  • ou git prune

ou uma combinação dos itens acima, conforme sugerido nesta pergunta: Reduzir o tamanho do repository git

Este guia sobre a remoção de dados confidenciais pode ser aplicado usando o mesmo método. Você estará reescrevendo o histórico para remover esse arquivo de todas as revisões em que estava presente. Isso é destrutivo e causará conflitos de recompra com qualquer outro check-out, portanto avise os colaboradores primeiro.

Se você quiser manter o binário disponível no repo para outras pessoas, então não há uma maneira real de fazer o que você quer. É praticamente tudo ou nada.

A chave para mim acabou sendo git repack -A -d -f e depois git gc para reduzir o tamanho do pacote git único que eu tinha.

Hy!

O Git só recebe objects que realmente precisa ao clonar repositorys (se eu entendi corretamente)

Assim, você pode corrigir o último commit removendo o arquivo adicionado por engano e, em seguida, enviar as alterações para o repository remoto (com a opção -f para replace o commit antigo no servidor)

Então, quando você criar um novo clone desse repository, o diretório .git deverá ser tão pequeno quanto antes do (s) arquivo (s) grande (s) confirmado (s).

Opcionalmente, se você quiser remover também os arquivos desnecessários do servidor, poderá excluir o repository no servidor e enviar sua cópia recém-clonada (que possui o histórico completo)

 git filter-branch --index-filter 'git rm --cached --ignore-unmatch Filename' --prune-empty -- --all 

Lembre-se de alterar o Filename do Filename para aquele que deseja remover do repository.

Veja “Removendo Objetos” no livro Pro Git:

http://git-scm.com/book/en/Git-Internals-Maintenance-and-Data-Recovery#Removing-Objects

Atualização: veja também o repo cleaner da BFG: http://rtyley.github.io/bfg-repo-cleaner/