Como parar o rastreamento e ignorar as alterações em um arquivo no Git?

1731

Eu clonei um projeto que inclui alguns .csprojarquivos. Eu não preciso / gosto que meus csprojarquivos locais sejam rastreados pelo Git (ou criados durante a criação de um patch), mas claramente eles são necessários no projeto.

Eu adicionei *.csprojao meu LOCAL .gitignore, mas os arquivos já estão no repositório.

Quando digito o status git, ele mostra minhas alterações nas csprojquais não estou interessado em acompanhar ou enviar para patches.

Como faço para remover o "rastreamento" desses arquivos do meu repositório pessoal (mas mantê-los na fonte para que eu possa usá-los) para não ver as alterações quando faço um status (ou crio um patch)?

Existe uma maneira correta / canônica de lidar com essa situação?

Joshua Ball
fonte
18
Uma pergunta muito útil, mas estou curioso para saber por que você não deseja acompanhar as alterações no .csprojarquivo, que é uma parte muito importante de qualquer projeto. Alterações no .csproj.userarquivo ou quaisquer .Publish.XMLarquivos eu posso totalmente entender não rastreamento, mas estou intrigado por que motivo você não gostaria de acompanhar o .csproj...
Owen Blacker
7
Talvez eles usem um IDE diferente?
Jarrett
3
Ironicamente, cheguei a esse segmento porque pretendo remover arquivos .suo de um repositório, mas mantê-los localmente. Para a posteridade, o desenvolvimento .Net exige que você mantenha os arquivos .csproj no repositório e essas alterações sempre devem ser rastreadas, a menos que você queira sentir a ira de outros desenvolvedores em seu projeto. Se alguma vez estiver inseguro, consulte o repositório de arquivos gitignore no GitHub: github.com/github/gitignore/blob/master/VisualStudio.gitignore
longda
1
@ Cupcake, a pergunta à qual você se vinculou foi escrita 15 dias após esta? Talvez você tenha outro em mente?
224146
As perguntas canônicas do @marflar não precisam necessariamente ser as mais antigas , apenas as melhores . O que eu

Respostas:

2129

Basta chamar git rm --cachedcada um dos arquivos que você deseja remover do controle de revisão. Desde que seus padrões locais de ignorância estejam corretos, você não verá esses arquivos incluídos na saída do status git.

Observe que esta solução remove os arquivos do repositório, portanto todos os desenvolvedores precisariam manter suas próprias cópias locais (não controladas por revisão) do arquivo

Para impedir que o git detecte alterações nesses arquivos, você também deve usar este comando:

git update-index --assume-unchanged [path]

O que você provavelmente quer fazer: (a partir de abaixo @Ryan Taylor answer )

  1. Isso é para dizer ao git que você deseja sua própria versão independente do arquivo ou pasta. Por exemplo, você não deseja substituir (ou excluir) os arquivos de configuração de produção / preparação.

git update-index --skip-worktree <path-name>

A resposta completa está aqui neste URL: http://source.kohlerville.com/2009/02/untrack-files-in-git/

Anthony
fonte
187
"git rm --cached <file>" remove o <file> do controle de versão, mantendo-o no repositório de trabalho. Se é o que você quer ...
Jakub Narębski
51
Mas quando outros puxam o repositório, seu próprio arquivo * .csproj será removido? Porque se queremos que o arquivo não seja rastreado, mas não excluído.
FMaz008
23
Se você estiver tentando remover TODOS os arquivos em um diretório, combine-o com o git ls-files: git ls-files | xargs git rm --cached- que removerá tudo do índice git em um determinado diretório sem excluir os arquivos reais.
Marco
129
git rm --cached -r <dir>trabalha recursivamente em uma pasta e em todos os arquivos nela.
Chris K
41
Isso interromperá o rastreamento do arquivo, preservá-lo localmente, mas fará com que seja excluído para qualquer pessoa que o puxar
Edward Newell
249

Se você fizer isso git update-index --assume-unchanged file.csproj, o git não verificará automaticamente as alterações no arquivo.csproj: isso impedirá que elas surjam no status git sempre que você as alterar. Assim, você pode marcar todos os seus arquivos .csproj dessa maneira - embora seja necessário marcar manualmente os novos que o repositório upstream envia a você. (Se você os tiver no seu .gitignoreou .git/info/exclude, os que você criar serão ignorados)

Não tenho muita certeza do que os arquivos .csproj são ... se eles são semelhantes às configurações do IDE (semelhantes aos arquivos .eclipse e .classpath do Eclipse), então eu sugiro que eles nunca devam ser controlados pela fonte em todos. Por outro lado, se eles fazem parte do sistema de compilação (como Makefiles), então claramente deveriam - e uma maneira de captar alterações locais opcionais (por exemplo, de um local.csproj a la config.mk) seria útil : divida a construção em partes globais e substituições locais.

araqnid
fonte
8
csproj é um arquivo de projeto C #, o que mantém o controle de quais arquivos estão incluídos no seu projeto e outras poucas configurações, deve ser fonte controlada para que o projeto de trabalho
faísca
4
Esta é a única resposta certa aqui! Uso a resposta @araqnids há anos e funciona exatamente como solicitado para resolver esse problema.
NHDaly
Qual é o significado do prefixo 'arquivo' no argumento do comando? Por que não é só .csproj?
GreenAsJade 27/11
1
Existe alguma maneira de detectar que isso foi feito para um arquivo ou para quais arquivos isso foi feito em um repositório? Estou um pouco nervoso em esquecer que fiz isso e depois me perguntando por que diabos esse arquivo não está sendo atualizado mais tarde!
GreenAsJade
4
@GreenAsJade: git ls-files -vmostrará arquivos que são assumidos inalterados com um indicador em minúsculas (por exemplo, em hvez do habitual Hpara arquivos em cache).
Amadan 27/11/14
238

Existem 3 opções, você provavelmente quer # 3

1. Isso manterá o arquivo local para você, mas o excluirá para qualquer outra pessoa quando eles puxarem.

git rm --cached <file-name> ou git rm -r --cached <folder-name>

2. Isso é para otimização, como uma pasta com um grande número de arquivos, por exemplo, SDKs que provavelmente nunca serão alterados. Ele diz ao git para parar de verificar sempre essa pasta enorme em busca de alterações, localmente, já que não terá nenhuma. O assume-unchangedíndice será redefinido e os arquivos serão substituídos se houver alterações de montante no arquivo / pasta (quando você puxar).

git update-index --assume-unchanged <path-name>

3. Isso é para dizer ao git que você deseja sua própria versão independente do arquivo ou pasta. Por exemplo, você não deseja substituir (ou excluir) os arquivos de configuração de produção / preparação.

git update-index --skip-worktree <path-name>

É importante saber que git update-index não será propagado com o git, e cada usuário precisará executá-lo independentemente.

Ryan Taylor
fonte
8
Esta resposta é a mais completa - oferece várias soluções com as ramificações de cada uma. O caso específico em que estou trabalhando tem uma senha incorporada em um arquivo de configuração. Quero propagar um arquivo de modelo e adicionar a senha à minha cópia. A cópia com a senha deve ser ignorada e não substituída.
bmacnaughton
1
Como posso verificar, em meu local, quais arquivos se aplicam a 'assumir inalterado' ou 'pular-área de trabalho'?
você precisa saber é o seguinte
3
@SupawatPusavanno para ver quais arquivos você previamente selecionadas para olhar assumir-inalterada ou ignorá-worktree neste resposta stackoverflow.com/questions/42363881/... - ele usa grepegit ls-files
Ryan Taylor
1
Resposta muito boa. Mas o git lança erro quando tento alternar para uma ramificação diferente: erro: "Suas alterações locais nos seguintes arquivos seriam substituídas pelo checkout ....." e a solução é ocultar as alterações antes de alternar e remover a ocultação quando você volta ao ramo.
PhantomReference
@ RyanTaylor: Eu tentei assumir o primeiro inalterado (não funcionou) e pular o comando worktree (não funcionou), quando verifico com o status do git que os arquivos não estão mostrando significa que o comando funcionou. Mas quando eu puxo o código novamente do repositório git origin it gives me error that your local changes would be overwrittennesses 2 arquivos também, então isso significa que não está acompanhando certo?
NeverGiveUp161
152

Este é um processo de duas etapas:

  1. Remova o rastreamento de arquivo / pasta - mas mantenha-os em disco - usando

    git rm --cached 
    

    Agora eles não aparecem como "alterados", mas ainda mostram como

        untracked files in  git status -u  
    
  2. Adicione-os a .gitignore

rjha94
fonte
56
Não, isso removerá o arquivo do rastreamento, preservará localmente, mas fará com que seja excluído para qualquer pessoa que puxar .
Edward Newell
1
No meu caso, adicionei acidentalmente uma pasta que não queria que fosse rastreada, e era disso que eu precisava.
Sonny
4
Sim, é de fato a resposta errada para a pergunta, mas provavelmente é a resposta certa para a maioria das pessoas que encontra essa pergunta nos resultados de pesquisa (como eu).
Andrew Spencer
95

A resposta aceita ainda não funcionou para mim

eu usei

git rm -r --cached.

git add.

git commit -m "corrigindo .gitignore"

Encontrei a resposta daqui

Buddhika Hasthanayake
fonte
Essa ligação é muito útil, especialmente para recursivamente remover todos os arquivos no .gitignore
rmcsharry
9
Voltei aqui 3 vezes, espero que eu possa me comprometer com a memória antes da próxima vez!
Harry Bosh
O comentário de @Edward Newell, como na resposta acima, também se aplica aqui: "isso removerá o arquivo do rastreamento, preservará localmente, mas fará com que seja excluído para quem puxar ".
ToJo
47

Esqueceu seu .gitignore?

Se você tem o projeto inteiro localmente, mas esqueceu de adicioná-lo, git ignore e agora está rastreando alguns arquivos desnecessários, use este comando para remover tudo

git rm --cached -r .

verifique se você está na raiz do projeto.

Então você pode fazer o habitual

Adicionar

git add .

Confirmar

git commit -m 'removed all and added with git ignore'

Empurrar

git push origin master

Conclusão

Espero que isso ajude as pessoas que precisam fazer alterações .gitignoreou esqueceram tudo juntas.

  • Remove todo o cache
  • Olha para o seu .gitignore
  • Adiciona os arquivos que você deseja rastrear
  • Empurra para o seu repo
Joe Lloyd
fonte
4
Quando você está falando sobre remover ou adicionar, esquece de dizer quando e onde. Removendo da lista de faixas? Do repositório? Do espaço do projeto local? Removendo ao puxar? Na confirmação? Na pressão? Infelizmente, todos os autores aqui têm o mesmo problema.
Gangnus 11/03/16
3
@ Gangnus Eu não acho que alguém tenha esclarecido o ponto que você está tentando enfatizar, porque é completamente óbvio que o arquivo não está sendo realmente removido do disco ou do repositório. Esta resposta especifica a ordem cronológica dos comandos. Não é misterioso ou mal explicado, como o seu comentário sugere.
Anthony Anthony
O comentário de @Edward Newell, como na resposta acima, também se aplica aqui: "isso removerá o arquivo do rastreamento, preservará localmente, mas fará com que seja excluído para quem puxar ".
ToJo
26

Conforme indicado em outras respostas, a resposta selecionada está errada.

A resposta para outra pergunta sugere que pode ser necessário ignorar a área de trabalho.

git update-index --skip-worktree <file>
the_new_mr
fonte
2
Não, na verdade não: --skip-worktreeé usado para manter o arquivo no repositório, mas para de rastrear suas alterações . Como a sua resposta diz: --skip-worktree é útil quando você instruir git para não tocar um arquivo específico nunca, porque os desenvolvedores devem alterá-lo
Erdal G.
4
@ErdalG. Exatamente. De acordo com a pergunta, eles desejam ignorar quaisquer alterações no arquivo, mas mantêm o arquivo no
repositório
Concorde com @the_new_mr --assume-unchangede --skip-worktreetenha um efeito semelhante, mas seus objetivos são totalmente diferentes. O primeiro é para acelerar o desempenho do git, enganando o git para não verificar arquivos específicos , enquanto o último é para ignorar alterações futuras em arquivos específicos , adequados para o tempo de execução, mas arquivos essenciais.
Victor Wong
22

Para economizar algum tempo, as regras adicionadas ao seu .gitignore podem ser usadas para remover vários arquivos / pastas, ou seja,

git rm --cached app/**/*.xml

ou

git rm --cached -r app/widgets/yourfolder/

etc

Pedro
fonte
Esta é uma causa muito boa solução em qualquer chance que você deseja corrigir o passo gitignore a passo
cutiko
15

Para impedir o monitoramento de um arquivo pelo git

git update-index --assume-unchanged [file-path]

E para revertê-lo novamente, use

git update-index --no-assume-unchanged [file-path]

Um repositório para referência para casos de uso semelhantes https://github.com/awslabs/git-secrets

shijin
fonte
1
A reversão da dica salvou vidas, obrigado!
Hamman Samuel
9

Muitas pessoas aconselham você a usar git update-index --assume-unchanged. De fato, essa pode ser uma boa solução, mas apenas no curto prazo.

O que você provavelmente vai querer fazer é esta: git update-index --skip-worktree.

(A terceira opção, que você provavelmente não deseja é:. git rm --cachedEle manterá seu arquivo local, mas será marcado como removido do repositório remoto.)

Diferença entre as duas primeiras opções?

  • assume-unchangedé temporariamente permitir ocultar modificações de um arquivo. Se você deseja ocultar as modificações feitas em um arquivo, modifique o arquivo e faça check-out em outra ramificação, será necessário usar as no-assume-unchangedmodificações ocultas provavelmente feitas.
  • skip-worktree irá segui-lo seja qual for o ramo que fizer o checkout, com suas modificações!

Caso de uso de assume-unchanged

Ele assume que esse arquivo não deve ser modificado e fornece uma saída mais limpa ao fazê-lo git status. Mas ao fazer o check-out para outra ramificação, é necessário redefinir o sinalizador e confirmar ou ocultar as alterações antes disso. Se você puxar com esta opção ativada, precisará resolver conflitos e o git não será mesclado automaticamente. Na verdade, ele apenas oculta modificações ( git statusnão mostra os arquivos sinalizados).

Gosto de usá-lo quando quero parar de rastrear alterações por um tempo + confirmar um monte de arquivos ( git commit -a) relacionados à mesma modificação.

Caso de uso de skip-worktree

Você tem uma classe de configuração contendo parâmetros (por exemplo, incluindo senhas) que seus amigos precisam alterar de acordo com a configuração deles.

  • 1: Crie uma primeira versão desta classe, preencha os campos que você pode preencher e deixe outros vazios / nulos.
  • 2: Confirme e envie-o para o servidor remoto.
  • 3: git update-index --skip-worktree MySetupClass.java
  • 4: Atualize sua classe de configuração com seus próprios parâmetros.
  • 5: Volte a trabalhar em outra funcionalidade.

As modificações que você fizer seguirão você em qualquer ramo. Aviso: se seus amigos também quiserem modificar essa classe, eles precisam ter a mesma configuração; caso contrário, suas modificações serão enviadas ao repositório remoto. Ao puxar, a versão remota do arquivo deve substituir a sua.

PS: faça um ou outro, mas não ambos, pois você terá efeitos colaterais indesejáveis. Se você quiser tentar outro sinalizador, desabilite o último primeiro.

Belka
fonte
7

Para dizer ao Git para não rastrear alterações no seu arquivo / pasta local (o status do git não detectará alterações), faça:

git update-index --skip-worktree path/to/file

E para dizer ao Git para rastrear as alterações na sua versão local mais uma vez (para que você possa confirmar as alterações), faça:

git update-index --no-skip-worktree path/to/file
Ruto Collins
fonte
1

resposta de uma linha git update-index --assume-unchanged [path]

Use isso sempre que você tiver um arquivo que esteja no repositório central e também no repositório local. Você precisa fazer alterações nesse arquivo, mas não deve ser preparado / confirmado no repositório central. Este arquivo não deve ser adicionado .gitignore. como novas alterações no arquivo, se introduzidas pelos administradores do sistema, os desenvolvedores seniores precisam ser distribuídos entre todos os repositórios locais.

Melhor exemplo: arquivo de configuração para conexões com o banco de dados . Em um repositório central, você terá todo o nome de usuário, senha, host e porta com valores de um servidor de banco de dados de produção. Mas no desenvolvedor local, você deve usar apenas um servidor de banco de dados local ou qualquer outro servidor de desenvolvimento (que sua equipe tenha configurado). Nesse caso, você deseja fazer alterações no arquivo de configuração, mas não deve ser comprometido com o repositório central.

Melhor

Seenivasan
fonte
0

Suponho que você esteja perguntando como remover TODOS os arquivos em uma pasta específica ou na pasta bin, em vez de selecionar cada arquivo separadamente.

Você pode usar este comando:

git rm -r -f /<floder-name>\*

Verifique se você está no diretório pai do diretório.
Este comando irá "excluir" recursivamente todos os arquivos que estão na lixeira / ou compilação / pastas. Com a palavra delete, quero dizer que o git fingirá que esses arquivos foram "excluídos" e que não serão rastreados. O git realmente marca esses arquivos no modo de exclusão.

Certifique-se de ter seu .gitignore pronto para as próximas confirmações.
Documentação: git rm

Vraj Pandya
fonte
0

O problema pode ser causado pela ordem de operação. Se você modificou o .gitignore primeiro e, em seguida, git rm --cached xxx, talvez seja necessário continuar a encontrar esse problema.

Solução correta:

  1. git rm --cached xxx
  2. modificou o .gitignore

Ordem invariável!

O .gitignore é recarregado após a modificação!

thearyong
fonte
0

Suponho que você esteja tentando remover um único arquivo do git tacking. por isso eu recomendaria o comando abaixo.

git update-index --assume-inalterado

Ex - git update-index --assume-inalterado .gitignore .idea / compiler.xml

Pankaj Sonani
fonte
0

Para ignorar quaisquer alterações em todos os arquivos (de um determinado tipo) em um diretório, tive que combinar algumas dessas abordagens; caso contrário, os arquivos foram criados se não existissem anteriormente.

Abaixo, "deletedir" é o nome do diretório no qual desejo não observar as alterações.

Primeiro, remova quaisquer novos arquivos existentes do cache de controle de alterações (sem remover do sistema de arquivos).

git status | grep "new file:" | cut  --complement -d " " -f1-4 | grep "^excludedir" | xargs git rm --cache

Você pode fazer o mesmo com modified:. renamed:é um pouco mais complicado, pois você terá que procurar no ->bit de postagem o novo nome do arquivo e fazer o pré- ->bit conforme descrito deleted:abaixo.

deleted: os arquivos são um pouco mais complicados, pois você não consegue atualizar o índice de um arquivo que não existe no sistema local

echo .deletedfiles >> .gitignore
git status | grep "deleted:" | cut  --complement -d " " -f1-4 | grep "^excludedir" > .deletedfiles
cat .deletedfiles | xargs -d '\n' touch
cat .deletedfiles | xargs -d '\n' git add -f
cat .deletedfiles | xargs -d '\n' git update-index --assume-unchanged
cat .deletedfiles | xargs -d '\n' rm

O último comando da lista acima removerá os arquivos novamente do seu sistema de arquivos, portanto, fique à vontade para omitir isso.

Em seguida, bloqueie o rastreamento de alterações nesse diretório

git ls-files excludedir/ | xargs git update-index --skip-worktree
git update index --skip-worktree excludedir/
mpag
fonte
0

Uma abordagem quase sem comando do git foi dada nesta resposta :

Para ignorar certos arquivos para cada repositório local :

  1. Crie um arquivo ~/.gitignore_global, por exemplo, touch ~/.gitignore_globalno seu terminal.
  2. Corra git config --global core.excludesfile ~/.gitignore_globalpela primeira vez.
  3. Escreva os caminhos de arquivo / diretório que você deseja ignorar ~/.gitignore_global. por exemplo modules/*.H, que será assumido como estando no seu diretório de trabalho, ou seja $WORK_DIR/modules/*.H.

Para ignorar determinados arquivos para um único repositório local :

  1. Execute a terceira etapa acima para arquivo .git/info/excludedentro do repositório, ou seja, escreva os caminhos de arquivo / diretório que você deseja ignorar .git/info/exclude. por exemplo modules/*.C, que será assumido como estando no seu diretório de trabalho, ou seja $WORK_DIR/modules/*.C.
Engenheiro Livre de Herpes
fonte
0

Aplicar .gitignore ao presente / futuro

Este método aplica o comportamento padrão do .gitignore e não requer a especificação manual dos arquivos que precisam ser ignorados .

Não é --exclude-from=.gitignoremais possível usar : / - Aqui está o método atualizado:

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

#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

#optionally add anything to the index that was previously ignored but now shouldn't be:
git add *

#commit again
#optionally use the --amend flag to merge this commit with the previous one instead of creating 2 commits.

git commit -m "re-applied modified .gitignore"

#other devs who pull after this commit is pushed will see the  newly-.gitignored files DELETED

Se você também precisar limpar os arquivos recém-ignorados do histórico de consolidação da filial ou se não desejar que os arquivos recém-ignorados sejam excluídos de futuras tentativas , consulte esta resposta .

goofology
fonte
-1

depois de pesquisar muito tempo, encontre uma maneira de fazer isso. alias um comando git em .gitconfig.like no projeto android studio , antes do checkout branch reverter o arquivo de configuração e depois pule , após o checkout branch use sedchange config file para a minha configuração local. checkoutandmodifylocalproperties = !git update-index --no-skip-worktree local.properties && git checkout local.properties && git checkout $1 && git update-index --skip-worktree local.properties && sed -i '' 's/.*sdk.dir.*/sdk.dir=\\/Users\\/run\\/Library\\/Android\\/sdk/g' local.properties && :

chinaanihchen
fonte