Remova um arquivo de um repositório Git sem excluí-lo do sistema de arquivos local

3048

Meu commit inicial continha alguns arquivos de log. Eu adicionei *logao meu .gitignoree agora quero remover os arquivos de log do meu repositório.

git rm mylogfile.log

removerá um arquivo do repositório, mas também o removerá do sistema de arquivos local.

Como posso remover este arquivo do repositório sem excluir minha cópia local do arquivo?

mveerman
fonte
14
Vale a pena notar que a resposta mais votada é perigosa para alguns. Se você estiver usando um repositório remoto do que quando envia o seu local, puxe para outro lugar os arquivos que você removeu do git, somente serão excluídos . Isso é mencionado em uma das respostas, mas não comentado.
RichieHH

Respostas:

4354

No arquivo man :

Quando --cachedé fornecido, o conteúdo faseado deve corresponder à ponta da ramificação ou ao arquivo no disco, permitindo que o arquivo seja removido apenas do índice.

Então, para um único arquivo:

git rm --cached mylogfile.log

e para um único diretório:

git rm --cached -r mydirectory
bdonlan
fonte
151
Facilmente esquecido, porque não é tão auto-explicativo quanto svn rm --keep-local.
Martin
114
Mas como preservo os arquivos em servidores remotos? Isso mantém o local, mas se eu pressionar e puxar de outro servidor, o arquivo será excluído. Eu também adicionei um .gitignore para o arquivo, mas ele ainda é removido
Spankmaster79
6
Isso ainda remove os arquivos git pullse você estiver por trás do commit depois #git rm
Petr Peller
9
Vale ressaltar que, depois de executar o comando na resposta, você precisa usar git commit -m "Commit message"e git push. Se você tiver outras alterações em etapas (verifique com git status), elas também serão confirmadas no momento.
Sinjai 11/09/17
9
Como esta é a resposta mais aceita e não faz, o que é solicitado, vou dizer o que faço. Eu uso o comando git rm --cached mylogfile.loge excluo o arquivo do repositório. Para evitar a perda do arquivo no sistema produtivo, faço um backup do arquivo e puxo depois disso. O arquivo é excluído como mencionado anteriormente e precisa ser copiado novamente do seu backup. Isso é bastante doloroso, mas não encontrei uma solução melhor para esse problema.
Marcel grolms
275

Para remover uma pasta inteira do repositório (como arquivos de novo compartilhador), faça o seguinte:

git rm -r --cached folderName

Eu havia comprometido alguns arquivos de novo compartilhamento e não queria que eles persistissem para outros usuários do projeto.

Sam Tyson
fonte
13
Apenas uma observação adicional para futuros visitantes: não use uma GUI para "sincronizar" a confirmação de volta ao repositório. Isso fará com que os arquivos retornem ao seu repositório local. Você precisa fazer um Git Push repo branchpara remover os arquivos do controle remoto.
precisa
211

Você também pode remover arquivos do repositório com base no seu .gitignore sem excluí-los do sistema de arquivos local:

git rm --cached `git ls-files -i -X .gitignore`

Ou, alternativamente, no Windows Powershell:

git rm --cached $(git ls-files -i -X .gitignore)
nulo
fonte
7
Não funciona no Windows. git ls-files -i -X ​​.gitignore funciona, mas não sei como enviar os arquivos para 'git rm'. voce sabe como fazer isso?
Erik Z
17
Funciona no Windows se você usar o Git Bash em vez do cmd-console
Andreas Zita
17
Amo isso. Funcionou, exceto que eu tinha alguns arquivos que acabaram tendo espaços no nome do arquivo. Eu modifiquei solução aqui para isso: git ls-files -i -X .gitignore | xargs -I{} git rm --cached "{}". Por favor, considere modificar ou adicionar esta solução para a resposta aqui, porque é uma ótima ferramenta para ter ...
mpettis
Eu não tentei, mas ele deve ser testado, ele removerá também arquivos como o .gitkeepque preserva uma pasta vazia no repositório. Por exemplo. .gitignorepasta uploadse o repositório é forçado a acompanhar .gitkeep. Ao remover tudo do repo sob uploadsele removerá também .gitkeep.
Vladimir Vukanac 07/07/16
Esta sugestão funcionou perfeitamente no powershell: git rm --cached $ (git ls-files -i -X ​​.gitignore)
geekandglitter
89

Conforme minha resposta aqui: /programming/6313126/how-to-remove-a-directory-in-my-github-repository

Para remover a pasta / diretório ou arquivo apenas do repositório git e não do local, tente 3 etapas simples.


Etapas para remover o diretório

git rm -r --cached File-or-FolderName
git commit -m "Removed folder from repository"
git push origin master

Etapas para ignorar essa pasta nas próximas confirmações

Para ignorar essa pasta das próximas confirmações, crie um arquivo na raiz chamado .gitignore e coloque o nome dessa pasta nela. Você pode colocar quantas quiser

O arquivo .gitignore ficará assim

/FolderName

remover diretório

eirenaios
fonte
@gaurav feliz que ajudou!
eirenaios
69

Além disso, se você confirmou dados confidenciais (por exemplo, um arquivo contendo senhas), exclua-os completamente do histórico do repositório. Aqui está um guia explicando como fazer isso: http://help.github.com/remove-sensitive-data/

BoD
fonte
13
Esta resposta deve incluir os comandos necessários para concluir esta tarefa em vez de criar um link para outro site.
Florian Lemaitre
1
Gostaria também de observar que achei mais fácil e rápido o uso da ferramenta de limpeza de repositórios git bfg .
Lubed Up Slug
64

Uma solução mais genérica:

  1. Edite o .gitignorearquivo.

    ECHO mylogfile.log >> .gitignore

  2. Remova todos os itens do índice.

    git rm -r -f --cached .

  3. Recrie o índice.

    git add .

  4. Fazer nova confirmação

    git commit -m "Removed mylogfile.log"

mAsT3RpEE
fonte
2
Isso realmente excluirá o arquivo?
Mr_and_Mrs_D
6
Do GitHub? NÃO. Se você já empurrou para o github, ele não o removerá do site. Mas ele atualizará seu repositório git local.
MST3RpEE
5
O comentário que você excluiu foi mais eliminado na verdade :) O problema com a solução rm --cashedé que ela acabará excluindo o arquivo quando você o puxar - certo? E não é isso que as pessoas querem quando dizem "Remover um arquivo do repositório sem excluí-lo do sistema de arquivos local ". Agora, por que a solução acima aceita está além de mim - provavelmente o OP estava trabalhando sozinho e nunca foi puxado? Não sei. Eu entendo o problema do github "uma vez empurrado sempre lá" ofc
Mr_and_Mrs_D
Eu não acho que exista uma solução 100%, a menos que você pergunte o próprio github. Por enquanto, atenha-se a isso. Copie o arquivo, adicione ao gitignore, faça o git rm -r real, confirme, pressione, restaure o arquivo. Você conseguiu encontrar outra solução?
MST3RpEE
9
Meu problema não é o github - é que o arquivo será realmente excluído dos colegas de trabalho quando eles puxarem . Eu não quero que o arquivo a ser excluído. Isso me causou grandes problemas no passado. Então, eu queria saber se existe realmente uma solução que realmente não apaga o arquivo. Veja também o comentário na resposta aceita: stackoverflow.com/questions/1143796/…
Mr_and_Mrs_D
24

O Git permite que você ignore esses arquivos, assumindo que eles não são alterados. Isso é feito executando o git update-index --assume-unchanged path/to/file.txtcomando Depois de marcar um arquivo como tal, o git ignorará completamente qualquer alteração nesse arquivo; eles não aparecerão ao executar o status git ou git diff, nem serão comprometidos.

(Em https://help.github.com/articles/ignoring-files )

Portanto, não a exclua, mas ignore as alterações para sempre. Eu acho que isso só funciona localmente, então os colegas de trabalho ainda podem ver alterações, a menos que executem o mesmo comando acima. (Ainda é necessário verificar isso.)

Nota: Isso não está respondendo diretamente à pergunta, mas é baseado nas perguntas de acompanhamento nos comentários das outras respostas.

Rystraum
fonte
2
Hum, eu faço isso, mas vejo que o arquivo pode ser substituído se alguém fizer alterações no repositório.
AlxVallejo 15/09
17

Se você deseja apenas rastrear um arquivo e não excluir do repositório local e remoto, use este comando:

git update-index --assume-unchanged  file_name_with_path
Afraz Ahmad
fonte
2
Embora essa seja uma boa resposta, é importante observar que isso não "rastreia" um arquivo no sentido de que as pessoas geralmente usam essa palavra com o Git, onde um arquivo não rastreado é aquele que não está no histórico do repositório e nunca foi encontrado. . O que essa resposta faz é manter o arquivo no repositório, mas impedir que o Git note que as alterações foram feitas nele. Isso tem algumas diferenças significativas - o mais importante é que o arquivo ainda está presente para outras pessoas e, se alguém fizer alterações nele e você puxar, sua cópia local poderá ser substituída sem confirmação.
Soren Bjornstad 22/10/19
8

As respostas acima não funcionaram para mim. Eu costumava filter-branchremover todos os arquivos confirmados.

Remova um arquivo de um repositório git com:

git filter-branch --tree-filter 'rm  file'

Remova uma pasta de um repositório git com:

git filter-branch --tree-filter 'rm -rf directory'

Isso remove o diretório ou arquivo de todas as confirmações.

Você pode especificar uma confirmação usando:

git filter-branch --tree-filter 'rm -rf directory' HEAD

Ou um intervalo:

git filter-branch --tree-filter 'rm -rf vendor/gems' t49dse..HEAD

Para enviar tudo para o controle remoto, você pode:

git push origin master --force
Martijn Mellens
fonte
2
Isto combinado com git rm -r --cached NAMEé o truque para removê-lo de seu repositório git local e impedi-lo de afetar qualquer um que puxa mais tarde (por excluir o histórico do arquivo ou diretório a partir do git.)
notbad.jpeg
1
Isso reescreve a história do git e você precisaria pressionar --force depois, isso está um pouco fora do escopo com a pergunta que eu acho. Em um repositório público famoso, você não pode simplesmente mudar a linha da história dessa maneira, pois todos os que já clonaram o repositório teriam problemas ao puxar.
Guillaume Perrot #
0

Ignore os arquivos, remova os arquivos do git, atualize o git (para a remoção).

Nota: isso não trata do histórico de informações confidenciais.

Esse processo definitivamente requer alguma compreensão do que está acontecendo com o git. Com o tempo, tendo conseguido isso, aprendi a executar processos como:

1) Ignore os arquivos

  • Adicione ou atualize o projeto .gitignorepara ignorá-los - em muitos casos, como o seu, o diretório pai, por exemplolog/ será o regex a ser usado.
  • confirmar e enviar por push a .gitignorealteração do arquivo (não tenho certeza se o envio é necessário, lembre-se, nenhum dano será feito).

2) Remova os arquivos do git (apenas).

  • Agora remova os arquivos do git (apenas) com git remove --cached some_dir/
  • Verifique se eles ainda permanecem localmente (deveriam!).

3) Adicione e confirme essa alteração (essencialmente, essa é uma alteração para "adicionar" para excluir itens, apesar do comando "adicionar" confuso de outra forma!)

  • git add .
  • git commit -m"removal"
Michael Durrant
fonte