Git: Como remover o arquivo do commit histórico?

113

Eu me comprometo com id 56f06019 (por exemplo). Nesse commit, enviei acidentalmente um arquivo grande (50Mb). Em outro commit, adiciono o mesmo arquivo, mas no tamanho certo (pequeno). Agora meu repo quando clonei é muito pesado :( Como remover aquele arquivo grande do histórico do repo para reduzir o tamanho do meu repo?

marioosh
fonte
no meu caso, não é um arquivo grande, mas um arquivo de configuração que contém os créditos do banco de dados. Eu estava estudando git, mas não conhecia o .gitignore.
Rashi
1
relacionada help.github.com/articles/...
Trevor Boyd Smith

Respostas:

165

O capítulo 9 do livro Pro Git tem uma seção sobre como remover objetos .

Deixe-me descrever brevemente as etapas aqui:

git filter-branch --index-filter \
    'git rm --cached --ignore-unmatch path/to/mylarge_50mb_file' \
    --tag-name-filter cat -- --all

Como a opção de rebasing descrita antes, filter-branché a operação de reescrita. Se você publicou a história, você terá que --forceempurrar os novos refs.

A filter-branchabordagem é consideravelmente mais poderosa do que a rebaseabordagem, uma vez que

  • permite que você trabalhe em todos os branches / refs de uma vez,
  • renomeia qualquer tag na hora
  • opera de forma limpa, mesmo que tenha havido vários commits de mesclagem desde a adição do arquivo
  • opera de forma limpa, mesmo se o arquivo foi (re) adicionado / removido várias vezes no histórico de (a) ramificação (s)
  • não cria novos commits não relacionados, mas sim os copia enquanto modifica as árvores associadas a eles. Isso significa que coisas como commits assinados, notas de commit etc. são preservados

filter-branch mantém backups também, então o tamanho do repo não diminuirá imediatamente, a menos que você expire os reflogs e a coleta de lixo:

rm -Rf .git/refs/original       # careful
git gc --aggressive --prune=now # danger
ver
fonte
1
É importante notar que isso não parece funcionar no Windows cmd.exe. Parece funcionar bem com o cygwin.
Nome falso de
2
Consegui fazer o git filter-branch funcionar usando aspas duplas em vez de aspas simples (no Windows Server 2012 cmd.exe)
JCii
1
O que funcionou para mim foi essa linha de comando de ramificação de filtro. git filter-branch --force --index-filter 'git rm --ignore-unmatch --cached PathTo/MyFile/ToRemove.dll' -- fbf28b005^.. Então rm --recursive --force .git/refs/originale rm --recursive --force .git/logs depois eu usei o git prune --expire now e git gc --aggressive Isso funcionou melhor para mim do que as etapas exatas listadas acima. Obrigado por incluir o link para o livro Git Pro, pois era inestimável.
dacke.geo
Após o comando filter-branch, a única maneira de baixar o tamanho da pasta .git era seguir o comando encontrado aqui: stackoverflow.com/questions/1904860/… git -c gc.reflogExpire = 0 -c gc. reflogExpireUnreachable = 0 -c gc.rerereresolved = 0 \ -c gc.rerereunresolved = 0 -c gc.pruneExpire = agora gc "$ @"
Steve Ardis
Para reduzir o repo, usei os comandos listados no documento git filter-branch: git-scm.com/docs/…
Ludovic Ronsin
0

Você precisará fazer o rebase do git no modo interativo. Veja um exemplo aqui: Como posso remover um commit no GitHub? e como remover commits antigos .

Se o seu commit está em HEAD menos 10 commits:

$ git rebase -i HEAD~10

Após a edição do seu histórico, você precisa empurrar o "novo" histórico, você precisa adicionar o +para forçar (consulte o refspec nas opções de push ):

$ git push origin +master

Se outras pessoas já clonaram seu repositório, você irá avisá-los, pois você acabou de alterar o histórico.

Loïc d'Anterroches
fonte
3
Isso não remove o arquivo grande da história. Além disso, a maneira canônica de forçar push é git push --forceou git push -f(que não exige que as pessoas conheçam o alvo de push do branch)
ver
Com base na pergunta, o novo arquivo é exatamente igual ao antigo, ou seja, o mesmo caminho. É por isso que você não pode usar diretamente git rmno caminho.
Loïc d'Anterroches
2
@sehe, se você fizer um rebase eliminando o commit com o arquivo enorme, ele desaparece para sempre.
vonbrand
@vonbrand apenas daquele branch que você rebaseou. Não estou presumindo que o branch 'de' seja excluído. Mas sim, se você excluir um ramo da árvore de revisão, isso ajudará: _
ver
@sehe, claro, você tem que perseguir todos os branches contendo o commit ofensivo. Se for antes de alguma complexidade no repo, você terá que reorganizar muito. Mas o rebase é a ferramenta para isso.
vonbrand
0

Tentei usar a seguinte resposta no windows https://stackoverflow.com/a/8741530/8461756

As aspas simples não funcionam no Windows, você precisa de aspas duplas.

Seguir funcionou para mim.

git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PathRelativeRepositoryRoot / bigfile.csv" - --all

Depois de remover o arquivo grande, consegui enviar minhas alterações para o github master.

Sandeep Dixit
fonte
0

Você pode usar um comando simples para excluir

 git rm -r -f app/unused.txt 
 git rm -r -f yourfilepath
mini desenvolvedor
fonte