Como posso fazer o git ignorar futuras revisões de um arquivo?

140

Eu criei uma versão padrão de um arquivo incluído em um repositório git. É importante que quando alguém clona o repositório, ele recebe uma cópia desse arquivo. No entanto, gostaria de definir o git para que ele ignore as alterações nesse arquivo posteriormente. .gitignorefunciona apenas em arquivos não rastreados.

Minha motivação é que este arquivo contenha informações específicas da máquina. Gostaria de fornecer valores padrão, permitindo que as pessoas façam alterações locais que não serão enviadas de volta ao repositório de origem, criando conflitos de mesclagem quando obtemos novas alterações.

Geralmente somos muito preguiçosos e usamos git add .muito, por isso tenho certeza de que, se não posso dizer ao git para ignorar esse arquivo, as alterações nele acabarão sendo comprometidas e enviadas por push.

Para resumir,

  1. Gostaria de criar um arquivo, chamá-lo default_values.txtque é adicionado ao meu repositório git e é incluído quando alguém clona esse repositório.
  2. git add .não deve adicionar default_values.txtao commit.
  3. Esse comportamento deve ser passado para qualquer clone do repositório.
Marc
fonte
1
Você pode usar os ganchos do git para ter um gancho de pré-confirmação que abortaria uma confirmação se o arquivo modificado for default_values.txt (digamos)?
Sateesh
1
Os puristas do Git diriam não ser preguiçoso e usar a área de preparação corretamente, é para isso que serve.
Xint0
Os puristas do Git diriam usar scripts borrados / limpos. É a solução mais sustentável.
Adam Dymitruk
1
Xint0: verdadeiro. mas como impedir que outras pessoas façam check-in acidentalmente?
Alan #
possível duplicata dos arquivos de configuração específicos da máquina de
confirmação

Respostas:

115

Como muitos outros mencionaram, uma boa solução moderna é:

git update-index --skip-worktree default_values.txt

Isso ignorará as alterações nesse arquivo, local e upstream, até que você decida permitir novamente com:

git update-index --no-skip-worktree default_values.txt

Você pode obter uma lista de arquivos marcados como ignorados:

git ls-files -v . | grep ^S

Observe que --skip-worktree, diferentemente , o --assume-unchangedstatus será perdido assim que uma alteração a montante for realizada.

humor
fonte
2
Se alguém puxa o repositório e edita o arquivo, as alterações em seu diretório são ignoradas? Espero que eles precisem digitar --no-skip-worktreepara adicionar suas alterações.
Neaumusic
3
O que é feito com suas mudanças é controlado por eles. Em outras palavras, eles teriam que definir skip-worktree no arquivo em seu repositório se não quisessem que suas alterações fossem enviadas. Se for um arquivo que deve ser enviado a todos e, em seguida, todas as alterações subsequentes serão ignoradas, todos deverão seguir as mesmas instruções.
Moodboom
3
Observe que talvez você precise desfazer o --skip-worktreestatus de um arquivo antes de poder alternar ramificações, se esse mesmo arquivo for rastreado na outra ramificação.
Moodboom
3
hmm, ele funciona ... depois que eu fiz alguma mudança no arquivo não foi mostrado na git status, mas quando tentei checkout para diferentes ramo, eu tenho error: Your local changes to the following files would be overwritten by checkout: , mesmo -f não ajudaerror: Entry 'wix-stores-merchant-app/demo/credentials.js' not uptodate. Cannot merge.
ykravv
1
Eu tenho estes alias para git ignoree git unignore.
Michael - Onde está Clay Shirky em
48

O que você está procurando é git update-index --assume-unchanged default_values.txt.

Consulte os documentos para obter mais detalhes: http://www.kernel.org/pub/software/scm/git/docs/git-update-index.html

tamasd
fonte
11
isso não funciona. embora faça o git adicionar. ignorar o arquivo na filial local, um clone do arquivo não tem este comportamento (se você mudar default_values.txt no arquivo clonado, ele será adicionado ao comprometer com "add git.")
Marc
6
Sim, porque você está definindo apenas para o repositório local. Você não pode enviar esse tipo de informação.
tamasd
8
@ Indradhanush - esta solução não atende ao critério 3 - "o comportamento deve ser passado para qualquer clone do repositório" - e é por isso que não o aceitei. Não significa que não é uma boa resposta.
Marc
Eu nunca notei o terceiro critério. Porque eu não estava procurando por isso. :)
Indradhanush Gupta
3
Para arquivos de configuração locais com configurações de aplicativos particulares, é provável que você queira usar em skip-worktreevez de assume-unchangedmais informações stackoverflow.com/questions/13630849/…
Aaron Hoffman
22

A abordagem que eu geralmente vi é criar um arquivo com um nome diferente, por exemplo: default_values_template.txt e colocar default_values.txt no seu .gitignore. Instrua as pessoas a copiar default_values_template.txt para default_values.txt em seus espaços de trabalho locais e faça as alterações necessárias.

Laurence Gonsalves
fonte
hmmm ... talvez eu pudesse escrever um gancho para copiar automaticamente default_values_template para default_values ​​se default_values ​​não existir?
Marc
2
Essa é a maneira mais comum de resolver isso na minha experiência. É praticamente o caminho de menor resistência, pois "simplesmente funciona", e você pode facilmente fazer seu código verificar se o arquivo de configuração local existe e fornecer um erro útil, se não existir.
Jani Hartikainen
Eu acho que a solução é realmente fazer algo assim, de preferência com um script executado sempre que você extrair ou clonar. Uma idéia seria que qualquer coisa com uma extensão específica (digamos .basefile) seja copiada para um arquivo com a extensão descartada e, em seguida, o nome do arquivo seja adicionado ao .gitignore nesse diretório. Então, eu criaria um arquivo default_values.txt.basefile e confirmaria isso. Eu não tenho o git ou o perl costeletas para fazer isso, mas vou perguntar a um amigo quem sabe e informar como isso funciona.
Marc
1
@AdamDymitruk: Sim, a limpeza / manchas pode ser usada neste caso, mas está longe de ficar claro que essa é a melhor opção. Por exemplo, isso tornará bastante difícil se as pessoas realmente quiserem alterar o arquivo, pois a limpeza / mancha ficará no caminho. Na verdade, eu preferiria a abordagem descrita aqui.
sleske
1
Pego uma sugestão do próprio git (especificamente git hooks) e uso o .samplesufixo. Então, no seu casodefault_values.txt.sample
tir38 03/04
5

Dê uma olhada em smudge / clean scripting. Dessa forma, você pode controlar o arquivo da versão, mas quando o check-out for feito, será "borrado", substituindo os dados genéricos / de marcador de lugar por dados específicos da máquina no arquivo.

Quando você o confirma, você o "limpa" substituindo as informações específicas da máquina por informações genéricas ou de espaço reservado.

Os scripts smudge / clean devem ser determinísticos, pois, aplicando-os várias vezes, em ordens diferentes, será o equivalente a apenas executar o último na sequência.

O mesmo pode ser aplicado com senhas se você precisar expor seu repositório, mas o conteúdo pode conter informações confidenciais.

Adam Dymitruk
fonte
Os scripts Clean and Smudge são locais ou fazem parte do repositório?
Alan
sim. :) ... ou seja, você pode compartilhar a mancha limpa através do repositório, mas não é uma boa ideia quando eles contêm dados confidenciais, como senhas de produção. Se isso não for uma preocupação, o git exige que você ative explicitamente o script. Caso contrário, as pessoas poderiam fazer coisas maliciosas via github e outros repositórios compartilhados para outros usuários.
Adam Dymitruk
Eu preciso ler um pouco mais sobre isso. Basicamente, quero configurar um projeto que tenha um padrão user.jsonque precise ser substituído pelos creds de cada desenvolvedor, mas não quero que o desenvolvedor verifique acidentalmente seus creds.
Alan em Alan
Eu pesquisaria em torno de scripts de exemplo de manchas limpas. Veja o que aparece. Além disso, pule na sala git irc no freenode. Você receberá ajuda imediatamente.
Adam Dymitruk 10/01
3

Eu resolvi isso definindo o filtro "limpo" para simplesmente classificar o conteúdo do arquivo no índice.

git show :path/to/myfile deve apenas imprimir o conteúdo do índice para o arquivo especificado, para que possamos usá-lo em um script para substituir a cópia de trabalho pela cópia intocada no índice:

#! /bin/sh

git show :$1

Defina isso como o filtro "limpo" para o arquivo em questão (supondo que você o tenha colocado em "discard_changes"):

$ git config filter.ignore_myfile.clean "discard_changes path/to/myfile"
$ echo "path/to/myfile filter=ignore_myfile" >> .gitattributes

Infelizmente, não consigo encontrar uma maneira de tornar isso generalizável para vários arquivos, pois não há como saber qual arquivo estamos processando dentro do script limpo. Obviamente, não há nada que o impeça de adicionar uma regra de filtro diferente para cada arquivo, mas é um pouco desajeitado.

Haddon CD.
fonte
1

Encontrei uma solução que funciona para minha equipe. Compartilhamos nossos githooks por meio de links simbólicos e, após adicionar um arquivo de modelo ao git, adicionei um gancho de pré-confirmação que verifica se o arquivo de modelo foi modificado e, em caso afirmativo, eu git reset -- templatefile.txt. Se for o único arquivo alterado, eu também aboro a confirmação.

codificador de frutas
fonte
-1

Sugiro olhar para submódulos. Se você colocar os arquivos específicos da máquina em um submódulo, o git add deve ignorá-lo.

ivanpro
fonte
é uma boa ideia, mas também tenho que colocar o repositório de arquivo único no servidor git, o que é menos do que o ideal, apenas porque estamos usando o github e temos um número limitado de repositórios.
Marc
O @Marc analisa o Visual Studio Team Services, projetos privados gratuitos e ilimitados e repositórios git. Os quadros Kanban, item de trabalho e rastreamento de bugs, associam checkins a itens de trabalho, gerenciam sprints se você estiver no scrum ou em outros tipos de projeto. Além disso, possui excelentes ferramentas de compilação para compor contra várias plataformas, muitas coisas para mencionar que são gratuitas. Algumas pessoas o criticam porque é a Microsoft, mas ele supera o que o github tem a oferecer em termos de ferramentas, além da hospedagem de repositórios. Existem limites para o que você pode fazer de graça, mas raramente os excedo.
Aran Mulholland
@ Marc mais uma coisa que acho realmente útil é que posso configurar quantas contas eu quiser, portanto, se estou escrevendo um projeto para um cliente que deseja possuir o controle de origem, posso criar uma conta, usá-lo planejar, projetar e executar o projeto e, quando terminar, posso passar a propriedade da conta para o cliente.
Aran Mulholland