Git - Ignora arquivos durante a fusão

114

Tenho um repo chamado myrepono beanstalkservidor remoto .

Eu o clonado em minha máquina local. Criou duas ramificações adicionais: staginge dev. Empurrei essas ramificações para o controle remoto também.

Agora:

 local                   remote                   server
 --------------------------------------------------------  
 master  ==> Pushes to  `master`  ==> deployed to `prod`
 staging ==> Pushes to  `staging` ==> deployed to `staging`
 dev     ==> Pushes to  `dev`     ==> deployed to `dev`

Eu tenho um arquivo chamado config.xmlque é diferente em cada ramo.

Desejo ignorar este arquivo apenas durante as fusões. Mas eu quero que isso seja incluído quando eu fizer checkout ou enviar de / para o branch repo.

O motivo pelo qual quero isso é que temos um script de implantação que puxa (verifica) o branch específico e implanta nos respectivos servidores. Portanto, precisamos que o config.xmlarquivo desse branch específico vá para o servidor específico, conforme indicado acima, quando implantado.

Eu acho que .gitignorenão vai funcionar. quais são as outras opções? Observe que o arquivo ignorado deve fazer parte do checkout e do commit, o que é importante. ele deve ser ignorado apenas durante as fusões.

Obrigado!

Kevin Rave
fonte
Em seu modo padrão, git pull é a abreviação de git fetch seguido por git merge FETCH_HEAD. Portanto, suas declarações são um tipo de conflito entre si.
zzk
Bem, eu diria, é check-out. Não puxe. Vou atualizar a pergunta para ficar claro.
Kevin Rave
2
você já encontrou uma solução para isso? Os atributos do git são úteis apenas para o caso em que o arquivo tem conflitos entre as ramificações que estão sendo mescladas, portanto, nem sempre é suficiente.
pvinis de
você procurou em links simbólicos (não seguidos por git) ou mesmo hard links para o resgate?
Frank Nocke

Respostas:

94

Superei esse problema usando o comando git merge com a --no-commitopção e, em seguida, removi explicitamente o arquivo testado e ignorei as alterações no arquivo. Ex: diga que quero ignorar quaisquer alterações para myfile.txtproceder da seguinte forma:

git merge --no-ff --no-commit <merge-branch>
git reset HEAD myfile.txt
git checkout -- myfile.txt
git commit -m "merged <merge-branch>"

Você pode colocar as instruções 2 e 3 em um loop for, se tiver uma lista de arquivos para pular.

unmesh-gurjar
fonte
2
Eu adicionaria "--no-ff" se você quiser que um arquivo não seja sobrescrito quando a fusão acontecer na estratégia de avanço rápido.
Ilia Shakitko
1
então o que git reset HEAD myfile.txtfaz exatamente? Como isso ajuda com nosso objetivo aqui?
Kid_Learning_C
Como você coloca as linhas 2 e 3 em um loop?
AndroidDev
52

Acabei encontrando git attributes. Tentando. Trabalhando até agora. Não verifiquei todos os cenários ainda. Mas deve ser a solução.

Estratégias de mesclagem - atributos do Git

Kevin Rave
fonte
1
Aqui está o link correto para a seção de estratégias de mesclagem dos documentos de atributos do git: git-scm.com/book/en/v2/…
Adrian Laurenzi
3
Achei isso bem explicado em um artigo medium.com/@porteneuve/…
ShawnFeatherly
9
Isso parece ser um problema se não houver conflitos? Os arquivos ainda serão mesclados?
Brett
18

.gitattributes - é um arquivo de nível raiz de seu repositório que define os atributos para um subdiretório ou subconjunto de arquivos.

Você pode especificar o atributo para dizer ao Git para usar diferentes estratégias de mesclagem para um arquivo específico. Aqui, queremos preservar o existente config.xmlpara o nosso ramo. Precisamos definir o merge=ourspara config.xmlno .gitattributesarquivo.

merge=ours diga ao git para usar nosso arquivo (branch atual), se ocorrer conflito de mesclagem.

  1. Adicione um .gitattributesarquivo no nível raiz do repositório

  2. Você pode configurar um atributo para confix.xml no .gitattributesarquivo

    config.xml merge=ours
    
  3. E, em seguida, defina uma simulação para nossa estratégia de fusão com:

    $ git config --global merge.ours.driver true
    

Se você mesclar o branch do stagformulário dev, em vez de ter os conflitos de mesclagem com o arquivo config.xml, o config.xml do branch do stag será preservado em qualquer versão que você tinha originalmente.

Eigenharsha
fonte
15
Mas e se não houver conflito? Como sempre manter um determinado arquivo durante a fusão?
Igor Yalovoy de
2
@IgorYalovoy: Se não houver conflito ... bem, isso é um pouco complicado, pois na verdade funciona a partir de IDs de hash, mas: se config.xmlestiver completamente inalterado da base de mesclagem para qualquer versão de ponta de ramificação, o Git apenas pega a versão alterada, sem olhando para o merge.ours.drivercenário. Então você está correto em se preocupar.
Torek
1
copiar e colar de Git Docs: Merge Strategies - Git atributos. Link
kyb
Este método resulta em "commits de mesclagem" todas as vezes FYI.
rsmets de
2
"nosso" parece ser um nome arbitrário para a nova estratégia que está sendo introduzida. Achei isso confuso, porque theirsé uma estratégia de mesclagem embutida. Mas parece que se pode escrever <pattern> merge=foo, então git config --global merge.foo.driver true, e funcionará da mesma maneira.
Kyle Strand
8

Você pode começar usando git merge --no-commite, em seguida, editar a mesclagem da maneira que quiser, ou seja, removendo o teste config.xmlou qualquer outro arquivo e, em seguida, confirmar. Suspeito que você queira automatizar ainda mais depois disso usando ganchos, mas acho que valeria a pena passar manualmente pelo menos uma vez.

gcbenison
fonte
2
Não git attributesoferecem qualquer solução em linha reta? Eu não consigo entender isso. git-scm.com/book/en/…
Kevin Rave
4

Você pode usar .gitignorepara manter o arquivo config.xmlfora do repositório e, em seguida, usar um gancho post commit para enviar o config.xmlarquivo apropriado para o servidor.

Tlehman
fonte
1
Eu sei que isso é um tipo de hack. Estou tentando encontrar uma solução limpa. E quanto ao git attributes. Alguma ideia de como funciona? Eu não consigo entender isso. git-scm.com/book/en/…
Kevin Rave
1
Eu nunca ouvi falar deles, estou tentando aplicar o atributo merge = our, parece promissor.
tlehman
1
Os atributos do Git são incríveis! Você pode até mesmo dizer ao git como comparar arquivos não-texto, então você pode usar pdf2text para comparar PDFs!
tlehman
2

Exemplo:

  1. Você tem dois ramos: master,develop
  2. Você criou o arquivo no developramo e deseja ignorá-lo durante a fusão

Código:

git config --global merge.ours.driver true
git checkout master
echo "path/file_to_ignore merge=ours" >> .gitattributes
git merge develop

Você também pode ignorar arquivos com a mesma extensão

por exemplo, todos os arquivos com .txtextensão:

echo "*.txt merge=ours" >> .gitattributes
Sole Sensei
fonte
1

Aqui git-update-index - Registra o conteúdo do arquivo na árvore de trabalho para o índice.

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

Exemplo:-

git update-index --assume-unchanged somelocation/pom.xml

Sireesh Yarlagadda
fonte
Isso é bom para empurrar, mas ainda reclama quando puxar pode substituir o arquivo.
Rolf
1
você tentou adicionar sua entrada de arquivo no arquivo .gitignore. @Rolf
Sireesh Yarlagadda