Como fazer o Git "esquecer" um arquivo que foi rastreado, mas que agora está no .gitignore?

5402

Há um arquivo que estava sendo rastreado git, mas agora o arquivo está na .gitignorelista.

No entanto, esse arquivo continua aparecendo git statusapós ser editado. Como você força gita esquecê-lo completamente?

Ivan
fonte
16
git clean -Xparece semelhante, mas não se aplica a essa situação (quando os arquivos ainda estão sendo rastreados pelo Git). Estou escrevendo isso para quem procura uma solução para não seguir o caminho errado.
imz - Ivan Zakharyaschev 27/02
35
A única resposta real para isso está abaixo, veja git update-index --assume-unchanged. Esta solução 1) mantém o arquivo no servidor (índice), 2) permite modificá-lo livremente localmente.
Qwerty
8
Você precisa usar --skip-worktree, consulte: stackoverflow.com/questions/13630849/…
Doppelganger
77
Uma pergunta importante é: o arquivo deve permanecer no repositório ou não? Por exemplo, se alguém novo clona o repositório, deve obter o arquivo ou não? Se SIM , então git update-index --assume-unchanged <file>é correto eo arquivo permanecerá no repositório e as alterações não serão adicionados com git add. Se NÃO (por exemplo, havia algum arquivo de cache, arquivo gerado etc.), ele git rm --cached <file>será removido do repositório.
Martin
9
@Martin @Qwerty Everyon deve parar para informar sobre --assume-unchangedqual é o desempenho para evitar que o git verifique o status de grandes arquivos rastreados, mas prefere o --skip-worktreeque é para arquivos rastreados modificados que o usuário não deseja mais confirmar. Veja stackoverflow.com/questions/13630849/…
Philippe

Respostas:

5705

.gitignoreimpedirá que add -farquivos não rastreados sejam adicionados (sem um ) ao conjunto de arquivos rastreados pelo git; no entanto, o git continuará rastreando todos os arquivos que já estão sendo rastreados.

Para parar de rastrear um arquivo, você precisa removê-lo do índice. Isso pode ser alcançado com este comando.

git rm --cached <file>

Se você deseja remover uma pasta inteira, é necessário remover todos os arquivos nela de forma recursiva.

git rm -r --cached <folder>

A remoção do arquivo da revisão principal ocorrerá no próximo commit.

AVISO: Embora isso não remova o arquivo físico do seu local, os arquivos de outras máquinas de desenvolvedores serão removidos na próxima git pull.

CB Bailey
fonte
55
o processo que workd para mim foi 1. confirmar as alterações pendentes primeiro 2. git rm --cached <file> e comprometer novamente 3. adicionar o arquivo de .gitignore, cheque com git status e se comprometer novamente
mataal
117
Adicionando muito importante. Se o arquivo ignorado for modificado (mas, apesar disso, não deve ser confirmado), após a modificação e execução, git add .ele será adicionado ao índice. E o próximo commit o comprometeria no repositório. Para evitar isso, execute logo após tudo o que mataal disse mais um comando:git update-index --assume-unchanged <path&filename>
Dao
32
O método de @AkiraYamamoto também funcionou bem para mim. No meu caso, suprimi a saída, pois meu repositório tinha milhares de arquivos:git rm -r -q --cached .
Aaron Blenkush 11/11
85
Isso excluirá o arquivo no git pullentanto.
Petr Peller
22
O git rm --cached <file> apenas remove o arquivo do repositório, o git update-index --assume-inalterado <file> não mostra o arquivo em alterações não estágios e não faz com que o pull puxe novas alterações. Mas eu quero GIT simplesmente ignorar CONTEÚDO DE PLEEEEEASE ARQUIVO
Igor Semin
2610

A série de comandos abaixo removerá todos os itens do índice Git (não do diretório de trabalho ou repositório local) e atualiza o índice Git, respeitando o git ignorado. PS. Index = Cache

Primeiro:

git rm -r --cached . 
git add .

Então:

git commit -am "Remove ignored files"

Ou uma linha:

git rm -r --cached . && git add . && git commit -am "Remove ignored files"
Matt Frear
fonte
197
Para destacar a diferença entre esta resposta e a resposta aceita: Usando esses comandos, você não precisa conhecer realmente os arquivos afetados. (Imagine um diretório temporário com muitos arquivos aleatórios que devem ser limpos do índice).
Ludwig
53
O mesmo que a resposta aceita. Os arquivos serão excluídos git pull.
Petr Peller
73
Seria bom ter isso como um comando git padrão. Algo como git rmignored.
Berik
12
@gudthing -r significa "recursivo"
Mark
14
Com isso, você pode acabar adicionando outros arquivos inúteis que não estão no momento .gitignore. O que pode ser difícil de descobrir se, dependendo de quão barulho você git statusestiver após esse comando. Um comando que remove apenas arquivos recém-ignorados seria melhor. É por isso que eu prefiro a resposta de thSoft
KurzedMetal
1122

O git update-index faz o trabalho para mim:

git update-index --assume-unchanged <file>

Nota: Esta solução é realmente independente em.gitignore pois o gitignore é apenas para arquivos não rastreados.

editar: desde que esta resposta foi publicada, uma nova opção foi criada e deve ser preferida. Você deve usar o --skip-worktreeque é para arquivos rastreados modificados que o usuário não deseja mais confirmar e manter o --assume-unchangeddesempenho para evitar que o git verifique o status de grandes arquivos rastreados. Consulte https://stackoverflow.com/a/13631525/717372 para obter mais detalhes ...

git update-index --skip-worktree <file>
Konstantin
fonte
173
Esta é a resposta real. Incrível, na verdade, muito simples, não polui git statuse é realmente muito intuitivo. Obrigado.
Pablo Olmos de Aguilera C.
4
Eu optei pela rm [...] .solução boa o suficiente , pois pelo menos conseguia entender como funcionava. Eu não encontrei nenhuma excelente documentação sobre o que update-indexe --assume-unchangedfazer. Alguém pode adicionar como isso se compara ao outro, porque eu gostaria de remover todos os arquivos que teriam sido ignorados? (Ou um link para uma explicação clara?)
Brady Trainor
25
git update-index --assume-unchanged <path> …fará com que o git ignore as alterações no (s) caminho (s) especificado (s), independentemente de .gitignore. Se você puxar de um controle remoto e esse controle tiver alterações nesse caminho, o git falhará na mesclagem com um conflito e você precisará mesclar manualmente. git rm --cached <path> …fará com que o git pare de rastrear esse caminho. Se você não adicionar o caminho .gitignore, verá o caminho no futuro git status. A primeira opção possui menos ruído no histórico de confirmação do git e permite que as alterações no arquivo "ignorado" sejam distribuídas no futuro.
ManicDee
26
Estou bastante confuso sobre como essa não é a resposta aceita. A resposta aceita aqui claramente não está respondendo à pergunta real que está sendo feita. Esta resposta ignora as alterações no arquivo que está no repositório enquanto não o remove do repositório.
Dave Cooper
11
Esta resposta seria muito mais útil se explicasse exatamente o que o comando fornecido faz, por exemplo, como é diferente das outras soluções sugeridas.
precisa saber é
283
git ls-files --ignored --exclude-standard -z | xargs -0 git rm --cached
git commit -am "Remove ignored files"

Isso pega a lista dos arquivos ignorados e os remove do índice e confirma as alterações.

thSoft
fonte
7
Se você precisar removê-los também do diretório de trabalho, basta executar git ls-files --ignored --exclude-standard | xargs git rm . Eu acredito que esta resposta é a melhor! Porque é muito claro, do jeito Unix, e faz a coisa desejada de maneira direta, sem compor os efeitos colaterais de outros comandos mais complexos.
imz - Ivan Zakharyaschev
6
Ótima resposta; no entanto, o comando falhará se você tiver caminhos com espaços no meio, por exemplo: "My dir / my_ignored_file.txt"
David Hernandez
8
git ls-files --ignored --exclude-standard | sed 's /.*/"&"/' | xargs git rm --cached
David Hernandez
3
git rmreclamará se ls-filesnão corresponder a nada. Use xargs -r git rm ...para dizer para xargsnão executar git rmse nenhum arquivo corresponder.
Wolfgang
10
Seria melhor usar \ 0 como separador:git ls-files --ignored --exclude-standard -z|xargs -0 git rm --cached
Nils-o-mat
83

Eu sempre uso esse comando para remover os arquivos não rastreados. Saída limpa de uma linha, estilo Unix:

git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached

Ele lista todos os seus arquivos ignorados, substitui cada linha de saída por uma linha entre aspas para manipular caminhos com espaços internos e passar tudo para git rm -r --cached para remover os caminhos / arquivos / diretórios do índice.

David Hernandez
fonte
3
Ótima solução! Funcionou perfeitamente e se sente mais correta que a remoção de todos os arquivos, em seguida, adicioná-los de volta.
Jon Catmull
5
Eu também achei isso "mais limpo". Pode ser óbvio, mas apenas a execução da primeira parte git ls-files --ignored --exclude-standardpermite que você entenda / verifique primeiro quais arquivos o seu novo .gitignoreexcluir / remover antes de executar a final git rm.
JonBrave
Esteja ciente, falha nos nomes de arquivos com certos caracteres "desagradáveis", por exemplo \n. Eu publiquei minha solução para atender a isso.
JonBrave
3
Outra ressalva: ao puxar, isso fará com que o arquivo seja excluído nos diretórios de trabalho de outras pessoas, certo?
precisa saber é
tentei, mas não funcionou para mim: sed: 1: "s/.*/": unterminated substitute in regular expressionem um comando filter-branch em um repositório com espaços. (Parecia funcionar fora do ramo do filtro). Eu usei da respostagit ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached de @ JonBrave .
Goofology 12/08/19
71

mova-o para fora, confirme e depois mova-o novamente. Isso funcionou para mim no passado. Provavelmente, existe uma maneira 'mais cuidadosa' de conseguir isso.

Joel Hooks
fonte
2
Isso funcionou muito bem se você deseja ignorar vários arquivos que não foram ignorados anteriormente. Embora, como você disse, provavelmente haja uma maneira melhor para isso.
Oskar Persson 28/05
Foi exatamente o que eu fiz. Simplesmente mova os arquivos para uma pasta fora do git e, em seguida, "git add.", "Git commit". (Isso removeu os arquivos), adicione o gitignore, fazendo referência aos arquivos / pastas, confirme novamente para adicionar o arquivo gitignore ao git, copie / mova de volta para as pastas e elas devem ser ignoradas. Nota: parece que os arquivos foram excluídos do GIT, portanto provavelmente os removeriam de outros checkouts / puxões, como mencionado nas soluções acima, mas como você está fazendo cópias deles inicialmente, isso não é um problema para o IMHO. basta deixar o resto do conhecimento da equipe ...
Del
Essa é a maneira mais fácil de se livrar de pastas comprometidas incorretamente.
precisa saber é o seguinte
2
Parece ser o único caminho que eu posso ver. É um bug enorme (não 'recurso') no git que, assim que você adiciona um arquivo / pasta ao .gitignore, ele não apenas ignora esse arquivo a partir desse ponto - para sempre - em qualquer lugar.
JosephK
Isso funcionou depois que eu tive-los adicionado, e em seguida, após o fato adicionou-los para .gitignore
hanzolo
66

Se você não puder git rmum arquivo rastreado porque outras pessoas precisam dele (aviso, mesmo que você git rm --cached , quando outra pessoa receber essa alteração, os arquivos serão excluídos no sistema de arquivos). Isso geralmente é feito devido a substituições de arquivos de configuração, credenciais de autenticação etc. Por favor, consulte https://gist.github.com/1423106 para saber como as pessoas resolveram o problema.

Para resumir:

  • Faça com que seu aplicativo procure um arquivo ignorado config-overide.ini e use-o sobre o arquivo confirmado config.ini (ou, alternativamente, procure ~ / .config / myapp.ini ou $ MYCONFIGFILE)
  • Confirme o arquivo config-sample.ini e ignore o arquivo config.ini, tenha um script ou semelhante copie o arquivo conforme necessário, se necessário.
  • Tente usar a magia clean / smudge do gitattributes para aplicar e remover as alterações, por exemplo, borrar o arquivo de configuração como um checkout de uma ramificação alternativa e limpar o arquivo de configuração como um checkout do HEAD. Isso é complicado, eu não recomendo para o usuário iniciante.
  • Mantenha o arquivo de configuração em uma ramificação de implantação dedicada a ele que nunca é mesclada ao mestre. Quando você deseja implantar / compilar / testar, mescla esse ramo e obtém esse arquivo. Essa é essencialmente a abordagem smudge / clean, exceto o uso de políticas de mesclagem humana e módulos extra-git.
  • Anti-recommentação: Não use a função assumir inalterada, ela só terminará em lágrimas (porque mentir para si mesmo fará com que coisas ruins aconteçam, como a alteração perdida para sempre).
Seth Robertson
fonte
7
O git não removeria o arquivo se ele estivesse sujo no momento da exclusão. E se não estiver sujo, recuperar o arquivo seria tão fácil quanto git checkout <oldref> -- <filename>- mas seria verificado e ignorado.
amenthes
Com relação à sua última observação (sobre --assume-unchanged): ou isso é culto à carga e deve ser descartado, ou você pode explicar o porquê (do qual estou convencido) e se torna útil.
RomainValeri
57

Use isso quando:

1. Você deseja rastrear muitos arquivos ou

2. Você atualizou seu arquivo gitignore

Link da fonte: http://www.codeblocq.com/2016/01/Untrack-files-already-added-to-git-repository-based-on-gitignore/

Digamos que você já tenha adicionado / confirmado alguns arquivos ao seu repositório git e depois os adicione ao seu .gitignore; esses arquivos ainda estarão presentes no seu índice de repositório. Este artigo vamos ver como se livrar deles.

Etapa 1: confirmar todas as suas alterações

Antes de continuar, verifique se todas as alterações foram confirmadas, incluindo o arquivo .gitignore.

Etapa 2: Remova tudo do repositório

Para limpar seu repo, use:

git rm -r --cached .
  • rm é o comando remove
  • -r permitirá a remoção recursiva
  • –Cached irá remover apenas arquivos do índice. Seus arquivos ainda estarão lá.

O rmcomando pode ser implacável. Se você quiser tentar o que faz antes, adicione o -nou--dry-run sinalizador para testar as coisas.

Etapa 3: adicione novamente tudo

git add .

Etapa 4: confirmar

git commit -m ".gitignore fix"

Seu repositório está limpo :)

Envie as alterações para o controle remoto para ver as alterações efetivas também.

Dheeraj Bhaskar
fonte
1
Ele não excluirá os arquivos do repositório remoto? E se eu quiser manter os arquivos no repositório local e no repositório remoto, mas fazer o git "esquecê-los"?
Avishay28
AFAIK, isso não excluirá arquivos do histórico porque não estamos usando nenhum comando de alteração de histórico (corrija-me se estiver errado). Isso apenas adiciona um novo commit ao excluir arquivos ignorados no gitignore do git. Esses arquivos estarão lá no os comprometimentos históricos
Dheeraj Bhaskar 19/03/19
49

Eu consegui isso usando o filtro-ramo git . O comando exato que usei foi retirado da página de manual:

AVISO : isso excluirá o arquivo de todo o seu histórico

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

Este comando recriará todo o histórico de consolidação, executando git rmantes de cada consolidação e, portanto, eliminará o arquivo especificado. Não se esqueça de fazer backup antes de executar o comando, pois ele será perdido.

drrlvn
fonte
9
Isso mudará todos os IDs de confirmação, quebrando, assim, mesclagens de ramificações fora da sua cópia do repositório.
bdonlan
19
AVISO: isso excluirá o arquivo de todo o seu histórico. Era isso que eu estava procurando, para remover um arquivo completamente desnecessário e de grandes dimensões (saída que nunca deveria ter sido confirmada) que foi confirmada há muito tempo no histórico de versões.
Zebediah49 13/03/2013
48

O que não funcionou para mim

(No Linux), eu queria usar as postagens aqui sugerindo a ls-files --ignored --exclude-standard | xargs git rm -r --cachedabordagem. No entanto, (alguns dos) arquivos a serem removidos tinham uma nova linha / LF / incorporada \nem seus nomes. Nenhuma das soluções:

git ls-files --ignored --exclude-standard | xargs -d"\n" git rm --cached
git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached

lidar com esta situação (obter erros sobre arquivos não encontrados).

Então eu ofereço

git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached
git commit -am "Remove ignored files"

Isso usa o -zargumento para ls-files e o -0argumento para xargs para atender com segurança / corretamente caracteres "desagradáveis" nos nomes de arquivos.

Na página de manual git-ls-files (1) , afirma:

Quando a opção -z não é usada, os caracteres TAB, LF e barra invertida nos nomes dos caminhos são representados como \ t, \ n e \\, respectivamente.

então acho que minha solução é necessária se os nomes de arquivos tiverem algum desses caracteres.

JonBrave
fonte
1
Para mim, esta é a melhor solução. Tem um desempenho muito melhor que um git add .. Ele também contém as melhores melhorias de alguns comentários acima.
Nils-o-mat
Você pode adicionar o thSoft's git commit -am "Remove ignored files"posteriormente à sua resposta? Suas respostas combinadas me fez passar por coisas: j
Kando
Eu não entendo o propósito de git commit -a. Para mim git rm --cachedafetam exatamente o índice assim não há necessidade de preparar os arquivos depois ...
Jean Paul
23
  1. Atualize seu .gitignorearquivo - por exemplo, adicione uma pasta para a qual não deseja rastrear .gitignore.

  2. git rm -r --cached .- Remova todos os arquivos rastreados, incluindo os desejados e os indesejados. Seu código estará seguro enquanto você salvar localmente.

  3. git add .- Todos os arquivos serão adicionados novamente, exceto os arquivos .gitignore.


Gorjeta de chapéu para @AkiraYamamoto por nos indicar a direção certa.

Chen_Wayne
fonte
1
Que tal o voto negativo devido ao fato de que ele realmente não funcionará, pois você precisa de -r para executar rm de forma recursiva de qualquer maneira :) (Alguém não copiou corretamente) #
438 Aran
1
Aviso: Esta técnica não faz com que o git ignore o arquivo; em vez disso, faz com que o git exclua o arquivo. Isso significa que, se você usar esta solução, sempre que alguém fizer um git pull, o arquivo será excluído. Portanto, não é realmente ignorado. Veja a solução sugerindo git update-index --assume-inaltered para obter uma solução para a pergunta original.
orrd 15/09/17
16

Eu acho que talvez o git não possa esquecer totalmente o arquivo por causa de sua concepção ( seção "Instantâneos, não diferenças" ).

Esse problema está ausente, por exemplo, ao usar o CVS. O CVS armazena informações como uma lista de alterações baseadas em arquivos. Informações para o CVS são um conjunto de arquivos e as alterações feitas em cada arquivo ao longo do tempo.

Mas no Git, toda vez que você confirma ou salva o estado do seu projeto, basicamente tira uma foto do que todos os seus arquivos aparência de naquele momento e armazena uma referência a esse instantâneo. Portanto, se você adicionou o arquivo uma vez, ele sempre estará presente nesse instantâneo.

Estes 2 artigos foram úteis para mim:

git assume-inalterado vs skip-worktree e Como ignorar alterações nos arquivos rastreados com o Git

Baseando-me, faça o seguinte, se o arquivo já estiver rastreado:

git update-index --skip-worktree <file>

A partir deste momento, todas as alterações locais neste arquivo serão ignoradas e não serão remotas. Se o arquivo for alterado no controle remoto, ocorrerá conflito quando git pull. Stash não vai funcionar. Para resolvê-lo, copie o conteúdo do arquivo para o local seguro e siga estas etapas:

git update-index --no-skip-worktree <file>
git stash
git pull 

O conteúdo do arquivo será substituído pelo conteúdo remoto. Cole suas alterações de um local seguro para arquivar e execute novamente:

git update-index --skip-worktree <file>

Se todos que trabalham com o projeto tiverem git update-index --skip-worktree <file>problemas, os problemas pulldevem estar ausentes. Esta solução é adequada para arquivos de configurações, quando cada desenvolvedor tem sua própria configuração de projeto.

Não é muito conveniente fazer isso sempre, quando o arquivo foi alterado no controle remoto, mas pode protegê-lo contra a substituição por conteúdo remoto.

Boolean_Type
fonte
16

Siga as etapas a seguir em série, você ficará bem.

1. remova os arquivos adicionados por engano do diretório / armazenamento . Você pode usar o comando "rm -r" (para linux) ou excluí-los navegando nos diretórios. Ou mova-os para outro local no seu PC. [Talvez você precise fechar o IDE se estiver executando para mover / remover ]

2. adicione os arquivos / diretórios ao gitignorearquivo agora e salve-o.

3. agora remova- os do cache do git usando estes comandos (se houver mais de um diretório, remova-os um por um emitindo repetidamente este comando)

git rm -r --cached path-to-those-files

4. agora faça um commit e push , use estes comandos. Isso removerá esses arquivos do git remote e fará com que o git pare de rastrear esses arquivos.

git add .
git commit -m "removed unnecessary files from git"
git push origin
Shamsul Arefin Sajib
fonte
13

A resposta copiar / colar é git rm --cached -r .; git add .; git status

Este comando ignorará os arquivos que já foram confirmados em um repositório Git, mas agora os adicionamos .gitignore.

youhans
fonte
9

A resposta de Matt Fear foi o IMHO mais eficaz. A seguir, é apenas um script do PowerShell para quem está no Windows para remover apenas arquivos de seu repositório git que corresponda à sua lista de exclusão.

# Get files matching exclusionsfrom .gitignore
# Excluding comments and empty lines
$ignoreFiles =  gc .gitignore | ?{$_ -notmatch  "#"} |  ?{$_ -match  "\S"} | % {
                    $ignore = "*" + $_ + "*"
                    (gci -r -i $ignore).FullName
                }
$ignoreFiles = $ignoreFiles| ?{$_ -match  "\S"}

# Remove each of these file from Git 
$ignoreFiles | % { git rm $_}

git add .
Ameer Deen
fonte
Em que situação essa lista de arquivos não será igual ao recursivo --cached?
John Zabroski
8

Mova ou copie o arquivo para um local seguro, para não perdê-lo. Em seguida, git rm o arquivo e confirme. O arquivo ainda será exibido se você reverter para uma dessas confirmações anteriores ou para outra ramificação em que não foi removida. No entanto, em todas as confirmações futuras, você não verá o arquivo novamente. Se o arquivo estiver no git ignore, você poderá movê-lo novamente para a pasta e o git não o verá.

Apreche
fonte
34
git rm --cachedirá remover o arquivo do índice sem excluí-lo do disco, por isso não há necessidade de mover / copiar-lo afastado
bdonlan
7

O uso do git rm --cachedcomando não responde à pergunta original:

Como você força gita esquecer completamente [um arquivo]?

De fato, esta solução fará com que o arquivo seja excluído em todas as outras instâncias do repositório ao executar um git pull!

A maneira correta de forçar o git a esquecer um arquivo é documentada pelo GitHub aqui .

Eu recomendo a leitura da documentação, mas basicamente:

git fetch --all
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch full/path/to/file' --prune-empty --tag-name-filter cat -- --all
git push origin --force --all
git push origin --force --tags
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now

apenas substitua full/path/to/filepelo caminho completo do arquivo. Verifique se você adicionou o arquivo ao seu .gitignore.

Você também precisará (temporariamente) permitir empurrões de avanço rápido para seu repositório , pois está alterando seu histórico do git.

Skeets
fonte
5

O BFG foi projetado especificamente para remover dados indesejados, como arquivos grandes ou senhas, dos repositórios do Git, por isso possui um sinalizador simples que remove todos os grandes arquivos históricos (que não estão no seu commit atual): '--strip-blobs- maior que'

$ java -jar bfg.jar --strip-blobs-bigger-than 100M

Se você deseja especificar arquivos por nome, também pode fazer isso:

$ java -jar bfg.jar --delete-files *.mp4

O BFG é 10-1000x mais rápido que o git filter-branch e geralmente muito mais fácil de usar - consulte as instruções e exemplos de uso completos para obter mais detalhes.

Fonte: https://confluence.atlassian.com/bitbucket/reduce-repository-size-321848262.html

Meir Gerenstadt
fonte
5

Se você não quiser usar a CLI e estiver trabalhando no Windows, uma solução muito simples é usar o TortoiseGit , que possui a ação "Excluir (manter local)" no menu que funciona bem.

Peter T.
fonte
5

Gostei da resposta de JonBrave, mas tenho diretórios de trabalho confusos o suficiente que comprometem -a me assusta um pouco, então aqui está o que eu fiz:

git config - global alias.exclude-ignorado '! git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached && git ls-files -z --ignored --exclude-standard | xargs -0 git stage && git stage .gitignore && git commit -m "novo gitignore e remova arquivos ignorados do índice" '

dividindo:

git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached 
git ls-files -z --ignored --exclude-standard | xargs -0 git stage 
git stage .gitignore 
git commit -m "new gitignore and remove ignored files from index"
  • remover arquivos ignorados do índice
  • estágio .gitignore e os arquivos que você acabou de remover
  • comprometer
Jay Irvine
fonte
4

Isso não é mais um problema no último git (v2.17.1 no momento da redação).

O .gitignorefinalmente ignora os arquivos rastreados, mas excluídos. Você pode testar isso executando o seguinte script. A git statusdeclaração final deve relatar "nada a confirmar".

# Create empty repo
mkdir gitignore-test
cd gitignore-test
git init

# Create a file and commit it
echo "hello" > file
git add file
git commit -m initial

# Add the file to gitignore and commit
echo "file" > .gitignore
git add .gitignore
git commit -m gitignore

# Remove the file and commit
git rm file
git commit -m "removed file"

# Reintroduce the file and check status.
# .gitignore is now respected - status reports "nothing to commit".
echo "hello" > file
git status
Lloyd
fonte
Estou feliz que o git agora faz isso. No entanto, o OP estava perguntando sobre o rastreamento de modificações nos arquivos presentes no .gitignore, os arquivos não excluídos ainda mostrando um status.
mrturtle
2

No caso de já estar comprometido DS_Store:

find . -name .DS_Store -print0 | xargs -0 git rm --ignore-unmatch

Ignore-os por:

echo ".DS_Store" >> ~/.gitignore_global
echo "._.DS_Store" >> ~/.gitignore_global
echo "**/.DS_Store" >> ~/.gitignore_global
echo "**/._.DS_Store" >> ~/.gitignore_global
git config --global core.excludesfile ~/.gitignore_global

Finalmente, faça um commit!


fonte
2

Especialmente para os arquivos baseados em IDE, eu uso este:

Por exemplo, o slnx.sqlite, acabei de me livrar completamente da seguinte maneira:

git rm {PATH_OF_THE_FILE}/slnx.sqlite -f
git commit -m "remove slnx.sqlite"

Lembre-se de que alguns desses arquivos armazenam algumas configurações e preferências locais do usuário para projetos (como os arquivos que você abriu). Portanto, toda vez que você navega ou faz algumas alterações em seu IDE, esse arquivo é alterado e, portanto, faz check-out e mostra como existem alterações não confirmadas.

curiousBoy
fonte
2

A resposta aceita não "faz o Git " esquecer " um arquivo ..." (historicamente). Faz apenas o git ignorar o arquivo no presente / futuro.

Este método faz com que o git esqueça completamente os arquivos ignorados ( passado / presente / futuro), mas não exclui nada do diretório ativo (mesmo quando retirado novamente do controle remoto).

Este método requer o uso de /.git/info/exclude(preferencial) OU um pré-existente .gitignore em todas as confirmações que possuem arquivos a serem ignorados / esquecidos. 1

Todos os métodos de impor o git ignoram o comportamento depois que o fato reescreve o histórico e, portanto, têm ramificações significativas para quaisquer repositórios públicos / compartilhados / colaborativos que possam ser extraídos após esse processo. 2

Conselho geral: comece com um repositório limpo - tudo confirmado, nada pendente no diretório ou índice ativo e faça um backup !

Além disso, os comentários / histórico de revisões desta resposta ( e o histórico de revisões desta pergunta ) podem ser úteis / esclarecedores.

#commit up-to-date .gitignore (if not already existing)
#this command must be run on each branch

git add .gitignore
git commit -m "Create .gitignore"

#apply standard git ignore behavior only to current index, not working directory (--cached)
#if this command returns nothing, ensure /.git/info/exclude AND/OR .gitignore exist
#this command must be run on each branch

git ls-files -z --ignored --exclude-standard | xargs -0 git rm --cached

#Commit to prevent working directory data loss!
#this commit will be automatically deleted by the --prune-empty flag in the following command
#this command must be run on each branch

git commit -m "ignored index"

#Apply standard git ignore behavior RETROACTIVELY to all commits from all branches (--all)
#This step WILL delete ignored files from working directory UNLESS they have been dereferenced from the index by the commit above
#This step will also delete any "empty" commits.  If deliberate "empty" commits should be kept, remove --prune-empty and instead run git reset HEAD^ immediately after this command

git filter-branch --tree-filter 'git ls-files -z --ignored --exclude-standard | xargs -0 git rm -f --ignore-unmatch' --prune-empty --tag-name-filter cat -- --all

#List all still-existing files that are now ignored properly
#if this command returns nothing, it's time to restore from backup and start over
#this command must be run on each branch

git ls-files --other --ignored --exclude-standard

Por fim, siga o restante deste guia do GitHub (começando na etapa 6), que inclui avisos / informações importantes sobre os comandos abaixo .

git push origin --force --all
git push origin --force --tags
git for-each-ref --format="delete %(refname)" refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now

Outros desenvolvedores que obtêm do repositório remoto modificado agora devem fazer um backup e, em seguida:

#fetch modified remote

git fetch --all

#"Pull" changes WITHOUT deleting newly-ignored files from working directory
#This will overwrite local tracked files with remote - ensure any local modifications are backed-up/stashed

git reset FETCH_HEAD

Notas de rodapé

1 Como /.git/info/excludepode ser aplicado a todas as confirmações históricas usando as instruções acima, talvez os detalhes sobre a inserção de um .gitignorearquivo nas confirmações históricas necessárias estejam além do escopo desta resposta. Eu queria que um apropriado .gitignoreestivesse no commit raiz, como se fosse a primeira coisa que fiz. Outros podem não se importar, pois /.git/info/excludepodem realizar a mesma coisa, independentemente de onde .gitignoreexista no histórico de confirmação, e reescrever claramente o histórico é um assunto muito delicado, mesmo quando está ciente das ramificações .

FWIW, métodos potenciais podem incluir git rebaseou um git filter-branchque copia um externo .gitignore para cada confirmação, como as respostas a esta pergunta

2 A imposição do comportamento do git ignore após a confirmação dos resultados de um git rm --cachedcomando independente pode resultar na exclusão de arquivos recém-ignorados em futuras tentativas do controle remoto forçado. O --prune-emptysinalizador no git filter-branchcomando a seguir evita esse problema removendo automaticamente a confirmação somente do índice "excluir todos os arquivos ignorados" anterior. Reescrever o histórico do git também altera os hashes de confirmação, o que causará estragos em futuras solicitações de repositórios públicos / compartilhados / colaborativos. Por favor, entenda as ramificações completamente antes de fazer isso em um repositório desse tipo. Este guia do GitHub especifica o seguinte:

Diga a seus colaboradores para refazer , e não mesclar, quaisquer ramificações que eles criaram do histórico de repositório antigo (contaminado). Um commit de mesclagem pode reintroduzir parte ou toda a história corrompida que você acabou de dar ao trabalho de eliminar.

Soluções alternativas que não afetam o repositório remoto são git update-index --assume-unchanged </path/file>ou git update-index --skip-worktree <file>, exemplos dos quais podem ser encontrados aqui .

goofology
fonte
0

Se alguém com dificuldade no Windows e você deseja ignorar a pasta inteira, 'cd' deseja a 'pasta' e faça 'Git Bash Here'.

git ls-files -z | xargs -0 git update-index --assume-unchanged
RajVimalC
fonte
0

No meu caso aqui, eu tinha vários arquivos .lock em vários diretórios que precisava remover. Eu executei o seguinte e funcionou sem ter que entrar em cada diretório para removê-los:

git rm -r --cached **/*.lock

Fazer isso foi para cada pasta na 'raiz' de onde eu estava e excluiu todos os arquivos que correspondiam ao padrão.

Espero que isso ajude os outros!

DC.Skells
fonte