Remover arquivo do repository git (histórico)

(resolvido, veja a parte inferior do corpo da pergunta)
Procurando por isso há muito tempo, o que tenho até agora é:

  • http://dound.com/2009/04/git-forever-remove-files-or-folders-from-history/ e
  • http://progit.org/book/ch9-7.html

Praticamente o mesmo método, mas ambos deixam objects em arquivos de pacotes … Presos.
O que eu tentei:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch file_name' rm -Rf .git/refs/original rm -Rf .git/logs/ git gc 

Ainda tem arquivos no pacote, e é assim que eu sei:

 git verify-pack -v .git/objects/pack/pack-3f8c0...bb.idx | sort -k 3 -n | tail -3 

E isto:

 git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch file_name" HEAD rm -rf .git/refs/original/ && git reflog expire --all && git gc --aggressive --prune 

O mesmo…

Tentei truque clit git clone , ele removeu alguns dos arquivos (~ 3000 deles), mas os maiores arquivos ainda estão lá …

Eu tenho alguns arquivos legados grandes no repository, ~ 200M, e eu realmente não quero eles lá … E eu não quero redefinir o repository para 0 🙁

SOLUÇÃO: Este é o caminho mais curto para se livrar dos arquivos:

  1. check .git / packed-refs – meu problema era que eu tinha lá uma linha refs/remotes/origin/master para um repository remoto, delete-o, caso contrário o git não removeria esses arquivos
  2. (opcional) git verify-pack -v .git/objects/pack/#{pack-name}.idx | sort -k 3 -n | tail -5 git verify-pack -v .git/objects/pack/#{pack-name}.idx | sort -k 3 -n | tail -5 git verify-pack -v .git/objects/pack/#{pack-name}.idx | sort -k 3 -n | tail -5 – para verificar os maiores arquivos
  3. (opcional) git rev-list --objects --all | grep a0d770a97ff0fac0be1d777b32cc67fe69eb9a98 git rev-list --objects --all | grep a0d770a97ff0fac0be1d777b32cc67fe69eb9a98 – para verificar quais são esses arquivos
  4. git filter-branch --index-filter 'git rm --cached --ignore-unmatch file_names' – para remover um arquivo de todas as revisões
  5. rm -rf .git/refs/original/ – para remover o backup do git
  6. git reflog expire --all --expire='0 days' – para expirar todos os objects soltos
  7. git fsck --full --unreachable – para verificar se há algum object solto
  8. git repack -A -d – reembalagem
  9. git prune – para finalmente remover esses objects

Eu não posso dizer com certeza sem access aos dados do seu repository, mas eu acredito que provavelmente há um ou mais refs compactados ainda referenciando commits antigos de antes de você executar o git filter-branch . Isso explicaria porque o git fsck --full --unreachable não chama o blob grande de um object inacessível, mesmo que você tenha expirado o seu reflog e removido os refs originais (descompactados).

Aqui está o que eu faria (depois de git filter-branch e git gc ter sido feito):

1) Certifique-se de que as referências originais desapareceram:

rm -rf .git/refs/original

2) Expirar todas as inputs do reflog:

git reflog expire --all --expire='0 days'

3) Verifique se há refs antigos

Isso pode ser complicado, dependendo de quantos pacotes você tiver. Eu não sei de nenhum comando do Git que automatize isso, então eu acho que você terá que fazer isso manualmente. Faça um backup de .git/packed-refs . Agora edite .git/packed-refs . Verifique se há referências antigas (em particular, veja se ele compactou alguma das referências de .git/refs/original ). Se você encontrar algum antigo que não precise estar lá, exclua-o (remova a linha para esse ref).

Depois que você terminar de limpar o arquivo packed-refs compactado, veja se o git fsck percebe os objects inacessíveis:

git fsck --full --unreachable

Se isso funcionou, e o git fsck agora relata seu blob grande como inacessível, você pode passar para a próxima etapa.

4) Reembale seu arquivo compactado (s)

git repack -A -d

Isso garantirá que os objects inacessíveis sejam descompactados e sejam descompactados.

5) podar objects soltos (inacessíveis)

git prune

E isso deveria bastar. O Git deveria ter uma maneira melhor de gerenciar refs compactados. Talvez exista uma maneira melhor que eu não saiba. Na falta de uma maneira melhor, a edição manual do arquivo packed-refs compactado pode ser o único caminho a seguir.

Eu recomendo usar o BFG Repo-Cleaner , uma alternativa mais simples e rápida ao git-filter-branch especificamente projetado para rewrite arquivos do histórico do Git. Uma maneira de tornar sua vida mais fácil aqui é que ela realmente lida com todas as referências por padrão (todas as tags, ramificações, coisas como refs / remotes / origin / master, etc), mas também é 10 a 50 vezes mais rápida.

Você deve seguir cuidadosamente estes passos aqui: http://rtyley.github.com/bfg-repo-cleaner/#usage – mas o núcleo é apenas isto: baixe o jar do BFG (requer o Java 6 ou superior) e execute este comando :

 $ java -jar bfg.jar --delete-files file_name my-repo.git 

Qualquer arquivo chamado file_name (que não está no seu último commit) será totalmente removido do histórico do seu repository. Você pode então usar o git gc para limpar os dados mortos:

 $ git gc --prune=now --aggressive 

O BFG é geralmente muito mais simples de usar do que o git-filter-branch – as opções são adaptadas em torno desses dois casos de uso comuns:

  • Removendo Crazy Big Files
  • Removendo senhas, credenciais e outros dados privados

Divulgação completa: Sou o autor do Repo-Cleaner da BFG.

Eu achei isso bastante útil no que diz respeito à remoção de uma pasta inteira, pois o acima não me ajudou muito: https://help.github.com/articles/remove-sensitive-data .

Eu usei:

 git filter-branch -f --force \ --index-filter 'git rm -rf --cached --ignore-unmatch folder/sub-folder' \ --prune-empty --tag-name-filter cat -- --all rm -rf .git/refs/original/ git reflog expire --expire=now --all git gc --prune=now git gc --aggressive --prune=now 

Eu estava tentando me livrar de um arquivo grande na história, e as respostas acima funcionaram, até certo ponto. O ponto é: eles não funcionam se você tiver tags. Se a confirmação que contém o arquivo grande puder ser acessada a partir de uma tag, você precisará ajustar o comando filiais de filtro desta forma:

 git filter-branch --tag-name-filter cat \ --index-filter 'git rm --cached --ignore-unmatch huge_file_name' -- \ --all --tags 

Veja: Como faço para remover arquivos sensíveis do histórico do git

O acima irá falhar se o arquivo não existir em um rev. Nesse caso, a opção ‘–ignore-unmatch’ corrigirá:

 git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch ' HEAD 

Então, para obter todos os objects soltos da repostiry:

 git gc --prune='0 days ago' 

Você tem várias razões para um tamanho ainda maior do reit git gc após o git gc , já que ele não remove todos os objects soltos .

Eu detalhei essas razões em ” reduzir o tamanho do repository git ”

Mas um truque para testar no seu caso seria clonar o repository Git “limpo” e ver se o clone tem o tamanho apropriado.

(“limpo” repo ‘sendo aquele em que você aplicou o filter-branch , e então gc e prune )

Isso deve ser coberto pelo comando git obliterate no Git Extras ( https://github.com/visionmedia/git-extras ).

 git obliterate  

Eu tive o mesmo problema e encontrei um ótimo tutorial no github que explica passo a passo como se livrar de arquivos que você acidentalmente cometeu.

Aqui está um pequeno resumo do procedimento sugerido pelo Cupcake.

Se você tiver um arquivo chamado file_to_remove para remover do histórico:

 cd path_to_parent_dir git filter-branch --force --index-filter \ 'git rm --cached --ignore-unmatch file_to_remove' \ --prune-empty --tag-name-filter cat -- --all