Como resolver conflitos de mesclagem no Git

4769

Como resolvo conflitos de mesclagem no Git?

Spoike
fonte
31
A postagem do blog a seguir parece dar um exemplo muito bom de como lidar com conflitos de mesclagem com o Git, que devem levá-lo na direção certa. Manuseio e evitar conflitos na Git
mwilliams
4
Você pode configurar uma ferramenta de mesclagem (kdiff3 jebaird.com/2013/07/08/… ) e usar o git mergetool. Quando você trabalha em grandes equipes de desenvolvedores, sempre encontra conflitos de mesclagem.
Grady Cooper L
Não esqueça que você pode atenuar a maioria dos conflitos de mesclagem mesclando regularmente a jusante!
Ant P
8
Pergunta fascinante: feita em 2008, 100% aberto terminou sem nenhuma dica sobre o que realmente é (trata-se de GUI? Sobre os comandos git? Sobre semântica? Sobre empurrar / puxar ou apenas conflitos gerais?) - completamente sem resposta. 30 respostas, todas (até onde uma rápida olhada mostra) mais ou menos falando sobre diferentes ferramentas diff3 e de mesclagem, nenhuma aceita. A resposta mais votada menciona um comando que nem funciona imediatamente com uma gitinstalação padrão . Consegui acessar a página inicial do SE hoje, 2017, com 1,3 milhão de visualizações e milhares de votos nos dois sentidos. Fascinante.
AnoE

Respostas:

2912

Tentar: git mergetool

Ele abre uma GUI que o orienta em cada conflito e você escolhe como mesclar. Às vezes, requer um pouco de edição manual depois, mas geralmente é suficiente por si só. É muito melhor do que fazer a coisa toda com a mão, certamente.

De acordo com o comentário @ JoshGlover:

O comando

não abre necessariamente uma GUI, a menos que você instale uma. Correr git mergetoolpara mim resultou em vimdiffser usado. Você pode instalar um dos seguintes ferramentas para usá-lo em vez disso: meld, opendiff, kdiff3, tkdiff, xxdiff, tortoisemerge, gvimdiff, diffuse, ecmerge, p4merge, araxis, vimdiff, emerge.

Abaixo está o procedimento de exemplo a ser usado vimdiffpara resolver conflitos de mesclagem. Com base neste link

Etapa 1 : Execute os seguintes comandos no seu terminal

git config merge.tool vimdiff
git config merge.conflictstyle diff3
git config mergetool.prompt false

Isso definirá o vimdiff como a ferramenta de mesclagem padrão.

Etapa 2 : Execute o seguinte comando no terminal

git mergetool

Etapa 3 : Você verá uma exibição do vimdiff no seguinte formato

  ╔═══════╦══════╦════════╗
  ║       ║      ║        ║
  ║ LOCAL ║ BASE ║ REMOTE ║
  ║       ║      ║        ║
  ╠═══════╩══════╩════════╣
  ║                       ║
  ║        MERGED         ║
  ║                       ║
  ╚═══════════════════════╝

Essas 4 visualizações são

LOCAL - esse é o arquivo da ramificação atual

BASE - ancestral comum, como o arquivo parecia antes das duas alterações

REMOTO - arquivo que você está mesclando em sua filial

MERGED - mesclar resultado, é isso que é salvo no repositório

Você pode navegar entre essas visualizações usando ctrl+ w. Você pode acessar diretamente a visualização MERGED usando ctrl+ wseguido de j.

Mais informações sobre a navegação vimdiff aqui e aqui

Etapa 4 . Você pode editar a exibição MERGED da seguinte maneira

Se você deseja obter alterações do REMOTE

:diffg RE  

Se você deseja obter alterações do BASE

:diffg BA  

Se você deseja obter alterações de LOCAL

:diffg LO 

Etapa 5 . Salvar, Sair, Confirmar e Limpar

:wqa salvar e sair do vi

git commit -m "message"

git clean Remova arquivos extras (por exemplo, * .orig) criados pela ferramenta diff.

Peter Burns
fonte
54
Para sua informação, você pode usar git mergetool -ypara salvar algumas teclas pressionadas se estiver mesclando muitos arquivos de uma só vez.
davr
373
Bem, ele não abre necessariamente uma GUI, a menos que você instale uma. Correr git mergetoolpara mim resultou em vimdiffser usado. Você pode instalar um dos seguintes ferramentas para usá-lo em vez disso: meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse ecmerge p4merge araxis vimdiff emerge.
Josh Glover
31
Bom ponto Josh. No ubuntu, tive a melhor sorte com o meld, sua exibição de mesclagem em três direções não é ruim. No OSX, o git escolheu um bom padrão.
Peter Burns
18
Isso abriu o KDiff3. Que eu não tenho absolutamente nenhuma idéia de como usar.
David Murdoch
7
Você também pode usar o Beyond Compare 3 agora ( git mergetool -t bc3).
AzP 30/08/2012
1703

Aqui está um provável caso de uso, do topo:

Você fará algumas alterações, mas opa, você não está atualizado:

git fetch origin
git pull origin master

From ssh://[email protected]:22/projectname
 * branch            master     -> FETCH_HEAD
Updating a030c3a..ee25213
error: Entry 'filename.c' not uptodate. Cannot merge.

Portanto, você fica atualizado e tenta novamente, mas tem um conflito:

git add filename.c
git commit -m "made some wild and crazy changes"
git pull origin master

From ssh://[email protected]:22/projectname
 * branch            master     -> FETCH_HEAD
Auto-merging filename.c
CONFLICT (content): Merge conflict in filename.c
Automatic merge failed; fix conflicts and then commit the result.

Então você decide dar uma olhada nas mudanças:

git mergetool

Oh meu Deus, meu Deus, a montante mudou algumas coisas, mas apenas para usar minhas alterações ... não ... as alterações deles ...

git checkout --ours filename.c
git checkout --theirs filename.c
git add filename.c
git commit -m "using theirs"

E então tentamos uma última vez

git pull origin master

From ssh://[email protected]:22/projectname
 * branch            master     -> FETCH_HEAD
Already up-to-date.

Ta-da!

CoolAJ86
fonte
19
Este foi super útil, porque eu tinha um monte de erros fundir com arquivos binários (ativos de arte) e fundindo as parece sempre falhar, então eu preciso substituí-lo com o novo arquivo sempre e não "merge"
petrocket
188
Cuidado! O significado de - nossos e - deles é invertido. --ours == o controle remoto. - deles == local. Vejagit merge --help
mmell 04/03
57
No meu caso, confirmo que --theirs = repositório remoto, --ours = meu próprio repositório local. É o oposto dos comentários do @mmell.
Aryo #
24
@mmell Apenas em uma rebase, aparentemente. Vejathis question
Navin
184
Gente, "nossa" e "deles" é relativa ao fato de você estar ou não se fundindo ou reestruturando. Se você estiver mesclando , então "nosso" significa o ramo no qual você está mesclando e "deles" é o ramo no qual você está mesclando. Quando você está reestruturando , então "nosso" significa os commits nos quais você está reestruturando. , enquanto "deles" refere-se às confirmações que você deseja refazer.
736

Acho que as ferramentas de mesclagem raramente me ajudam a entender o conflito ou a resolução. Normalmente, sou mais bem-sucedido olhando os marcadores de conflito em um editor de texto e usando o git log como um complemento.

Aqui estão algumas dicas:

Dica um

A melhor coisa que eu encontrei é usar o estilo de conflito de mesclagem "diff3":

git config merge.conflictstyle diff3

Isso produz marcadores de conflito como este:

<<<<<<<
Changes made on the branch that is being merged into. In most cases,
this is the branch that I have currently checked out (i.e. HEAD).
|||||||
The common ancestor version.
=======
Changes made on the branch that is being merged in. This is often a 
feature/topic branch.
>>>>>>>

A seção do meio é a aparência do ancestral comum. Isso é útil porque você pode compará-lo com as versões superior e inferior para ter uma melhor noção do que foi alterado em cada ramificação, o que lhe dá uma idéia melhor sobre qual era o objetivo de cada alteração.

Se o conflito é apenas algumas linhas, isso geralmente torna o conflito muito óbvio. (Saber como resolver um conflito é muito diferente; você precisa estar ciente do que as outras pessoas estão trabalhando. Se estiver confuso, provavelmente é melhor chamar essa pessoa para o seu quarto para que elas possam ver o que você está procurando. às.)

Se o conflito for mais longo, recortarei e colarei cada uma das três seções em três arquivos separados, como "meu", "comum" e "deles".

Em seguida, posso executar os seguintes comandos para ver os dois pedaços de diferenças que causaram o conflito:

diff common mine
diff common theirs

Isso não é o mesmo que usar uma ferramenta de mesclagem, pois ela também inclui todos os blocos de diferenças não conflitantes. Acho que isso é perturbador.

Dica dois

Alguém já mencionou isso, mas entender a intenção por trás de cada pedaço de diferença geralmente é muito útil para entender de onde veio um conflito e como lidar com ele.

git log --merge -p <name of file>

Isso mostra todos os commits que tocaram nesse arquivo entre o ancestral comum e as duas cabeças que você está mesclando. (Portanto, não inclui confirmações que já existem nos dois ramos antes da mesclagem.) Isso ajuda a ignorar as diferenças, que claramente não são um fator no seu conflito atual.

Dica Três

Verifique suas alterações com ferramentas automatizadas.

Se você tiver testes automatizados, execute-os. Se você tem um cotão , execute isso. Se for um projeto montável, construa-o antes de confirmar, etc. Em todos os casos, é necessário fazer alguns testes para garantir que suas alterações não quebrem nada. (Heck, mesmo uma mesclagem sem conflitos pode quebrar o código de trabalho.)

Dica Quatro

Planejar com antecedência; comunicar com colegas de trabalho.

Planejar com antecedência e estar ciente do que os outros estão trabalhando pode ajudar a evitar conflitos de mesclagem e / ou a resolvê-los mais cedo - enquanto os detalhes ainda estão em mente.

Por exemplo, se você sabe que você e outra pessoa estão trabalhando em uma refatoração diferente que afetará o mesmo conjunto de arquivos, converse com antecedência e tenha uma noção melhor dos tipos de alterações que cada um de vocês é fazer. Você pode economizar tempo e esforço consideráveis ​​se realizar as alterações planejadas em série e não em paralelo.

Para grandes refatorações que abrangem uma grande faixa de código, considere fortemente trabalhar em série: todo mundo para de trabalhar nessa área do código enquanto uma pessoa realiza a refatoração completa.

Se você não pode trabalhar em série (devido à pressão do tempo, talvez), a comunicação sobre os conflitos de mesclagem esperados pelo menos ajuda a resolver os problemas mais cedo, enquanto os detalhes ainda estão em mente. Por exemplo, se um colega de trabalho estiver realizando uma série de confirmações disruptivas ao longo de um período de uma semana, você poderá optar por mesclar / refazer esse ramo de colegas de trabalho uma ou duas vezes por dia durante essa semana. Dessa forma, se você encontrar conflitos de mesclagem / rebase, poderá resolvê-los mais rapidamente do que se esperar algumas semanas para mesclar tudo em um único bloco.

Dica Cinco

Se você não tiver certeza de uma mesclagem, não a force.

A mesclagem pode parecer esmagadora, principalmente quando há muitos arquivos conflitantes e os marcadores de conflito cobrem centenas de linhas. Muitas vezes, ao estimar projetos de software, não incluímos tempo suficiente para itens de sobrecarga, como lidar com uma mescla gnarly, portanto, é uma pena passar várias horas dissecando cada conflito.

A longo prazo, planejar com antecedência e estar ciente do que os outros estão trabalhando são as melhores ferramentas para antecipar conflitos de mesclagem e preparar-se para resolvê-los corretamente em menos tempo.

Mark E. Haase
fonte
6
A opção diff3 é um ótimo recurso para mesclar. A única GUI que encontrei mostra que é o Perforce p4merge, que pode ser instalado e usado separadamente das outras ferramentas do Perforce (que eu não usei, mas ouvi reclamações).
Alxndr
3
Após uma tentativa de rebase que resultou em um conflito de mesclagem: $ git log --merge -p build.xml output: fatal: --merge sem MERGE_HEAD?
Ed Randall
e se eu tiver alterações em um arquivo do branch1 e exclusão desse arquivo no branch2. Como posso resolver esse conflito de mesclagem? Existe alguma maneira de usar o git onde eu possa mesclá-los mantendo as alterações de um ramo?
Honey
git config merge.conflictstyle diff3Obrigado senhor. Isso é incrível e me liberou de tentar encontrar (e pagar $$) por uma boa GUI de mesclagem de 3 maneiras. Na IMO, isso é melhor porque mostra o ancestral comum, bem como local / remoto, e mostra as últimas linhas de log de confirmação que (AFAIK) nenhuma GUI faz. As confirmações definitivamente ajudam a identificar qual código pertence a qual ramificação.
Ffxsam 04/04
Descobri que, às vezes, o estilo de conflito diff3 resulta em enormes pedaços diff, que são praticamente idênticos, enquanto o padrão produzirá pedaços menores e mais fáceis de gerenciar. Infelizmente, não tenho um reprodutor que possa ser usado para um relatório de erro. Mas se você encontrar esse problema, pode considerar desativar a opção temporariamente.
Dave Abrahams
348
  1. Identifique quais arquivos estão em conflito (o Git deve informar isso).

  2. Abra cada arquivo e examine as diferenças; O Git os demarca. Espero que seja óbvio qual versão de cada bloco manter. Pode ser necessário discuti-lo com outros desenvolvedores que confirmaram o código.

  3. Depois de resolver o conflito em um arquivo git add the_file.

  4. Depois de resolver todos os conflitos, execute git rebase --continueo comando que o Git disse para executar quando concluir.

davetron5000
fonte
38
@ Justin Pense no Git como rastreando conteúdo, em vez de rastrear arquivos. Então é fácil ver que o conteúdo que você atualizou não está no repositório e precisa ser adicionado. Essa maneira de pensar também explica por que o Git não rastreia pastas vazias: embora sejam tecnicamente arquivos, não há conteúdo para rastrear.
Gareth
7
o conteúdo está lá, o conflito ocorre porque há 2 versões do conteúdo. Portanto, "git add" não parece correto. E isso não funciona (git add, git commit) se você deseja confirmar apenas um arquivo após a resolução do conflito ("fatal: não é possível fazer um commit parcial durante uma mesclagem").
Dainius
1
Sim, tecnicamente, isso responde à pergunta que foi feita, mas não é uma resposta útil, na minha opinião, desculpe. Qual o sentido de tornar um ramo o mesmo que outro? Claro que uma fusão terá conflitos ..
Thufir
5
Thulfir: quem disse algo sobre tornar um ramo o mesmo que outro? Existem diferentes cenários em que você precisa mesclar, sem "tornar uma ramificação igual à outra". Uma é quando você termina um ramo de desenvolvimento e deseja incorporar suas alterações no ramo mestre; depois disso, o ramo de desenvolvimento pode ser excluído. Outra é quando você deseja refazer sua ramificação de desenvolvimento, a fim de facilitar a eventual mesclagem final no mestre.
Teemu Leisti
4
@JustinGrant cria git addarquivos no índice; ele não acrescentar nada ao repositório. git commitadiciona coisas ao repositório. Esse uso faz sentido para mesclagens - a mesclagem automaticamente monitora todas as alterações que podem ser mescladas automaticamente; é sua responsabilidade mesclar o restante das alterações e adicioná-las ao índice quando terminar.
Mark E. Haase
105

Confira as respostas na pergunta Stack Overflow Interrompendo uma mesclagem no Git , especialmente a resposta de Charles Bailey, que mostra como exibir as diferentes versões do arquivo com problemas, por exemplo,

# Common base version of the file.
git show :1:some_file.cpp

# 'Ours' version of the file.
git show :2:some_file.cpp

# 'Theirs' version of the file.
git show :3:some_file.cpp
Pat Notz
fonte
Confira também a opção "-m" para "git checkout -m" - ele permite que você extrair os diferentes moscas de volta para seu espaço de trabalho
qneill
Isso me salvou. Observar cada arquivo separadamente me permitiu lembrar o que eu estava procurando em cada ramo. Então eu poderia tomar a decisão de escolher.
Rohmer 14/05
99

Os conflitos de mesclagem acontecem quando são feitas alterações em um arquivo ao mesmo tempo. Aqui está como resolvê-lo.

git CLI

Aqui estão etapas simples que você deve fazer quando entrar em estado de conflito:

  1. Observe a lista de arquivos conflitantes com: git status(na Unmerged pathsseção).
  2. Resolva os conflitos separadamente para cada arquivo, usando uma das seguintes abordagens:

    • Use a GUI para resolver os conflitos: git mergetool(a maneira mais fácil).

    • Para aceitar remoto / outra versão, use: git checkout --theirs path/file. Isso rejeitará as alterações locais que você fez para esse arquivo.

    • Para aceitar a versão local / nossa, use: git checkout --ours path/file

      No entanto, você deve ter cuidado, pois alterações remotas que conflitos foram feitos por algum motivo.

      Relacionado: Qual é o significado preciso de "nosso" e "deles" no git?

    • Edite os arquivos em conflito manualmente e procure o bloco de código entre <<<<</ >>>>>e escolha a versão acima ou abaixo =====. Veja: Como os conflitos são apresentados .

    • Os conflitos de caminho e nome de arquivo podem ser resolvidos por git add/ git rm.

  3. Finalmente, rever os arquivos pronto para cometer usando: git status.

    Se você ainda tiver quaisquer arquivos sob Unmerged paths, e você conseguiu resolver o conflito manualmente, em seguida, deixar Git saber que você resolveu por: git add path/file.

  4. Se todos os conflitos foram resolvidos com êxito, confirme as alterações com: git commit -ae pressione para remoto como de costume.

Consulte também: Resolvendo um conflito de mesclagem na linha de comando no GitHub

Para um tutorial prático, verifique: Cenário 5 - Corrigindo conflitos de mesclagem por Katacoda .

DiffMerge

Usei com sucesso o DiffMerge, que pode comparar e mesclar visualmente arquivos no Windows, macOS e Linux / Unix.

Ele pode mostrar graficamente as alterações entre três arquivos e permite a mesclagem automática (quando seguro) e controle total sobre a edição do arquivo resultante.

DiffMerge

Fonte da imagem: DiffMerge (captura de tela do Linux)

Basta fazer o download e executar no repositório como:

git mergetool -t diffmerge .

Mac OS

No macOS, você pode instalar via:

brew install caskroom/cask/brew-cask
brew cask install diffmerge

E provavelmente (se não for fornecido), você precisará do seguinte invólucro extra simples colocado em seu PATH (por exemplo /usr/bin):

#!/bin/sh
DIFFMERGE_PATH=/Applications/DiffMerge.app
DIFFMERGE_EXE=${DIFFMERGE_PATH}/Contents/MacOS/DiffMerge
exec ${DIFFMERGE_EXE} --nosplash "$@"

Em seguida, você pode usar os seguintes atalhos de teclado:

  • - Alt- Up/ Downpara pular para as alterações anteriores / próximas.
  • - Alt- Left/ Rightpara aceitar alterações da esquerda ou da direita

Como alternativa, você pode usar o opendiff (parte do Xcode Tools), que permite mesclar dois arquivos ou diretórios para criar um terceiro arquivo ou diretório.

kenorb
fonte
79

Se você está fazendo pequenas confirmações frequentes, comece examinando os comentários de confirmação git log --merge. Em seguida git diff, mostrará os conflitos.

Para conflitos que envolvem mais do que algumas linhas, é mais fácil ver o que está acontecendo em uma ferramenta GUI externa. Eu gosto do opendiff - o Git também suporta vimdiff, gvimdiff, kdiff3, tkdiff, meld, xxdiff, emergir da caixa e você pode instalar outros: git config merge.tool "your.tool"você definirá a ferramenta escolhida e, git mergetoolapós uma falha na mesclagem, mostrará as diferenças no contexto.

Cada vez que você edita um arquivo para resolver um conflito, git add filenameatualiza o índice e seu diff não o mostra mais. Quando todos os conflitos forem tratados e seus arquivos tiverem sido git addeliminados, git commita fusão será concluída.

Paulo
fonte
8
Usar "git add" é o verdadeiro truque aqui. Você pode nem querer confirmar (talvez queira ocultar), mas é necessário "git add" para concluir a mesclagem. Acho que o mergetool faz a adição para você (embora não esteja na página de manual), mas se você fizer a mesclagem manualmente, precisará usar "git add" para concluir (mesmo que não queira confirmar).
nobar 25/10/10
47

Consulte Como os conflitos são apresentados ou, no Git, a git mergedocumentação para entender o que são marcadores de conflito de mesclagem.

Além disso, a seção Como resolver conflitos explica como resolver os conflitos:

Depois de ver um conflito, você pode fazer duas coisas:

  • Decida não mesclar. As únicas limpezas necessárias são redefinir o arquivo de índice para o HEADcommit para reverter 2. e limpar as alterações na árvore de trabalho feitas por 2. e 3 .; git merge --abortpode ser usado para isso.

  • Resolva os conflitos. O Git marcará os conflitos na árvore de trabalho. Edite os arquivos em forma e git addeles no índice. Use git commitpara selar o acordo.

Você pode solucionar o conflito com várias ferramentas:

  • Use uma ferramenta de fusão. git mergetoolpara iniciar uma ferramenta gráfica de mesclagem, que o ajudará na mesclagem.

  • Veja as diferenças. git diffmostrará uma comparação de três vias, destacando as alterações nas versões HEADe MERGE_HEAD.

  • Veja as diferenças de cada ramo. git log --merge -p <path>mostrará diffs primeiro para a HEADversão e depois a MERGE_HEADversão.

  • Veja os originais. git show :1:filenamemostra o ancestral comum, git show :2:filenamemostra a HEADversão e git show :3:filenamemostra a MERGE_HEADversão.

Você também pode ler sobre os marcadores de conflito de mesclagem e como resolvê-los na seção do livro do Pro Git , Conflitos básicos de mesclagem .

Peter Mortensen
fonte
42

Desejo minha versão completa ou a versão deles ou desejo revisar alterações individuais e decidir por cada uma delas.

Aceite totalmente a minha versão ou a deles :

Aceite minha versão (local, nossa):

git checkout --ours -- <filename>
git add <filename>              # Marks conflict as resolved
git commit -m "merged bla bla"  # An "empty" commit

Aceite a versão deles (remota, deles):

git checkout --theirs -- <filename>
git add <filename>
git commit -m "merged bla bla"

Se você deseja fazer para todos os arquivos de conflito, execute:

git merge --strategy-option ours

ou

git merge --strategy-option theirs

Revise todas as alterações e aceite-as individualmente

  1. git mergetool
  2. Revise as alterações e aceite uma das versões para cada uma delas.
  3. git add <filename>
  4. git commit -m "merged bla bla"

O padrão mergetoolfunciona na linha de comando . Como usar uma fusão de linha de comando deve ser uma pergunta separada.

Você também pode instalar uma ferramenta visual para isso, por exemplo, melde executar

git mergetool -t meld

Ele abrirá a versão local (nossa), a versão "base" ou "mesclada" (o resultado atual da mesclagem) e a versão remota (a deles). Salve a versão mesclada quando terminar, execute git mergetool -t meldnovamente até obter "Nenhum arquivo precisa ser mesclado " e vá para as Etapas 3. e 4.

Nenhuma idéia
fonte
Este comando: --theirs git checkout - <filename> mudado todos os arquivos para o deles, e não apenas <filename>
Donato
Na verdade eu estava errado. Isso atualiza apenas o arquivo especificado.
Donato
40

Para usuários do Emacs que desejam resolver conflitos de mesclagem semi-manualmente:

git diff --name-status --diff-filter=U

mostra todos os arquivos que requerem resolução de conflitos.

Abra cada um desses arquivos, um por um, ou todos de uma vez:

emacs $(git diff --name-only --diff-filter=U)

Ao visitar um buffer que exige edições no Emacs, digite

ALT+x vc-resolve-conflicts

Isso abrirá três buffers (o meu, o deles e o buffer de saída). Navegue pressionando 'n' (próxima região), 'p' (região de previsão). Pressione 'a' e 'b' para copiar a minha ou a região deles para o buffer de saída, respectivamente. E / ou edite o buffer de saída diretamente.

Quando terminar: Pressione 'q'. O Emacs pergunta se você deseja salvar esse buffer: sim. Depois de terminar um buffer, marque-o como resolvido executando a partir do teriminal:

git add FILENAME

Quando terminar com todos os tipos de buffers

git commit

para finalizar a mesclagem.

eci
fonte
33

Bônus:

Ao falar sobre puxar / buscar / mesclar nas respostas acima, gostaria de compartilhar um truque interessante e produtivo,

git pull --rebase

Este comando acima é o comando mais útil na minha vida git, que economizou muito tempo.

Antes de empurrar a sua mudança recém comprometido com servidor remoto, tente git pull --rebaseem vez git pulle manual mergee ele será automaticamente sincronizado últimas alterações de servidor remoto (com uma busca + merge) e irá colocar o seu local de última cometer no topo em git log. Não precisa se preocupar com puxar / mesclar manualmente.

Em caso de conflito, basta usar

git mergetool
git add conflict_file
git rebase --continue

Encontre detalhes em: http://gitolite.com/git-pull--rebase

Sazzad Hissain Khan
fonte
32

Simplesmente, se você sabe bem que as mudanças em um dos repositórios não são importantes e deseja resolver todas as mudanças em favor do outro, use:

git checkout . --ours

resolver alterações a favor do seu repositório ou

git checkout . --theirs

resolver alterações em favor do outro ou do repositório principal .

Ou então você terá que usar uma ferramenta de mesclagem da GUI para percorrer os arquivos um por um, dizer que a ferramenta de mesclagem é p4mergeou escrever o nome de alguém que você já instalou

git mergetool -t p4merge

e depois de terminar um arquivo, você precisará salvar e fechar, para que o próximo seja aberto.

Mohamed Selim
fonte
2
git checkout. --theirs resolvido meus problemas, graças
Ramesh Chand
se você preferir resolver conflitos tentar manualmente abrindo a pasta no código do Visual Studio, ele marca arquivos com conflitos e cores linhas de conflito dentro de cada um
Mohamed Selim
31

Siga as etapas a seguir para corrigir conflitos de mesclagem no Git:

  1. Verifique o status do Git: status do git

  2. Obtenha o patchset: git fetch (faça o checkout do patch correto no commit do Git)

  3. Efetue checkout de uma filial local (temp1 no meu exemplo aqui): git checkout -b temp1

  4. Puxe o conteúdo recente do master: git pull --rebase origin master

  5. Inicie o mergetool e verifique os conflitos e corrija-os ... e verifique as alterações na ramificação remota com sua ramificação atual: git mergetool

  6. Verifique o status novamente: status git

  7. Exclua os arquivos indesejados criados localmente pelo mergetool, geralmente o mergetool cria um arquivo extra com a extensão * .orig. Exclua esse arquivo, pois isso é apenas a duplicata e corrija as alterações localmente e adicione a versão correta dos seus arquivos. git add #your_changed_correct_files

  8. Verifique o status novamente: status git

  9. Confirme as alterações no mesmo ID de confirmação (isso evita um novo conjunto de patches separado): git commit --amend

  10. Enviar para o ramo principal: git push (para o seu repositório Git)

Chhabilal
fonte
28

Existem 3 etapas:

  1. Encontre quais arquivos causam conflitos por comando

    git status
    
  2. Verifique os arquivos nos quais você encontrará os conflitos marcados como

    <<<<<<<<head
    blablabla
    
  3. Altere para o modo que você deseja e, em seguida, confirme com comandos

    git add solved_conflicts_files
    git commit -m 'merge msg'
    
Qijun Liu
fonte
Trabalhou para mim! Obrigado!
Nuwan Jayawardene
Você deve prestar atenção se fizer isso durante o rebase. Você deve usar git rebase --continue vez de git commit
Samuel Dauzon
27

Você pode corrigir conflitos de mesclagem de várias maneiras, conforme detalhado por outras.

Eu acho que a chave real é saber como as mudanças fluem com os repositórios locais e remotos. A chave para isso é entender as ramificações de rastreamento. Descobri que penso no ramo de rastreamento como a 'peça que faltava no meio' entre mim, meu diretório local de arquivos reais e o controle remoto definido como origem.

Eu, pessoalmente, adquiri o hábito de duas coisas para ajudar a evitar isso.

Ao invés de:

git add .
git commit -m"some msg"

O que tem duas desvantagens -

a) Todos os arquivos novos / alterados são adicionados e podem incluir algumas alterações indesejadas.
b) Você não pode revisar a lista de arquivos primeiro.

Então, eu faço:

git add file,file2,file3...
git commit # Then type the files in the editor and save-quit.

Dessa forma, você é mais deliberado sobre quais arquivos são adicionados e também pode revisar a lista e pensar um pouco mais ao usar o editor da mensagem. Acho que também melhora minhas mensagens de confirmação quando uso um editor de tela cheia em vez da -mopção.

[Atualização - com o passar do tempo, mudei mais para:

git status # Make sure I know whats going on
git add .
git commit # Then use the editor

]

Além disso (e mais relevante para a sua situação), tento evitar:

git pull

ou

git pull origin master.

porque pull implica uma mesclagem e se você tiver alterações localmente que não deseja mesclar, poderá facilmente acabar com o código mesclado e / ou conflitos de mesclagem para código que não deveria ter sido mesclado.

Em vez disso, tento fazer

git checkout master
git fetch   
git rebase --hard origin/master # or whatever branch I want.

Você também pode achar útil:

git branch, fork, fetch, merge, rebase e clone, quais são as diferenças?

Michael Durrant
fonte
Ei, eu meio que entendi sua resposta. Mas como eu sou novo no github, mesclar conflitos, acho que há algo faltando. O que acontece com as suas modificações locais quando você faz git checkout mastere git fetch e git rebase --hard origin/master
Suhaib
Eu acredito que você deve adicionar mais detalhes sobre o que fazer. Outro exemplo que está me confundindo, você mencionou na sua resposta: nós git add .salvamos nossas modificações locais para que possamos acompanhar git checkout master? ou são dois cenários diferentes?
Suhaib 08/08/19
@MichaelDurrant $ git rebase --hard origin/master b5a30cc159ba8dd error: unknown option hard 'use: git rebase [-i] [opções] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>] ou: git rebase [-i] [ opções] [--exec <cmd>] [--onto <newbase>] --root [<branch>] ou: git rebase --continue | --abort | --skip | --edit-todo `
likejudo
24

A resposta de CoolAJ86 resume praticamente tudo. Caso você tenha alterações nas duas ramificações no mesmo trecho de código, será necessário fazer uma mesclagem manual. Abra o arquivo em conflito em qualquer editor de texto e você verá a seguinte estrutura.

(Code not in Conflict)
>>>>>>>>>>>
(first alternative for conflict starts here)
Multiple code lines here
===========
(second alternative for conflict starts here)
Multiple code lines here too    
<<<<<<<<<<<
(Code not in conflict here)

Escolha uma das alternativas ou uma combinação de ambas da maneira que você deseja que seja o novo código, enquanto remove sinais de igual e colchetes angulares.

git commit -a -m "commit message"
git push origin master
iankit
fonte
17
git log --merge -p [[--] path]

Parece que nem sempre funciona para mim e geralmente acaba exibindo todos os commit que eram diferentes entre os dois ramos, isso acontece mesmo quando se usa -- para separar o caminho do comando.

O que faço para solucionar esse problema é abrir duas linhas de comando e em uma execução

git log ..$MERGED_IN_BRANCH --pretty=full -p [path]

e no outro

git log $MERGED_IN_BRANCH.. --pretty=full -p [path]

Substituindo $MERGED_IN_BRANCHpela ramificação na qual mesclei e [path]pelo arquivo que está em conflito. Este comando registrará todas as confirmações, em forma de patch, entre ( ..) duas confirmações. Se você deixar um lado vazio, como nos comandos acima, o git usará automaticamente HEAD(o ramo no qual você está se fundindo neste caso).

Isso permitirá que você veja quais confirmações foram inseridas no arquivo nos dois ramos depois que eles divergiram. Geralmente facilita muito a solução de conflitos.

Brian Di Palma
fonte
16

Usando patience

Estou surpreso que ninguém mais tenha falado sobre resolver conflitos usando patiencea estratégia recursiva de mesclagem. Para um grande conflito de mesclagem, o uso patienceforneceu bons resultados para mim. A ideia é que ele tente combinar blocos em vez de linhas individuais.

Se você alterar o recuo do seu programa, por exemplo, a estratégia padrão de mesclagem do Git às vezes combina chaves simples {que pertencem a diferentes funções. Isso é evitado com patience:

git merge -s recursive -X patience other-branch

A partir da documentação:

With this option, merge-recursive spends a little extra time to avoid 
mismerges that sometimes occur due to unimportant matching lines 
(e.g., braces from distinct functions). Use this when the branches to 
be merged have diverged wildly.

Comparação com o ancestral comum

Se você tiver um conflito de mesclagem e quiser ver o que os outros tinham em mente ao modificar sua ramificação, às vezes é mais fácil comparar sua ramificação diretamente com o ancestral comum (em vez de nossa ramificação). Para isso você pode usar merge-base:

git diff $(git merge-base <our-branch> <their-branch>) <their-branch>

Normalmente, você deseja apenas ver as alterações para um arquivo específico:

git diff $(git merge-base <our-branch> <their-branch>) <their-branch> <file>
Conquilicultor
fonte
No meu caso, isso não resolveu bem os conflitos de mesclagem, pois, por algum motivo, mantinha linhas duplicadas de configuração nos projetos em C #. Apesar de ter sido mais amigável do que o arquivo inteiro é diferente, o que eu tinha antes
Mathijs Segers
15

A partir de 12 de dezembro de 2016, você pode mesclar filiais e resolver conflitos no github.com

Portanto, se você não quiser usar a linha de comando ou qualquer ferramenta de terceiros oferecida aqui a partir de respostas mais antigas , use a ferramenta nativa do GitHub.

Esta postagem do blog explica em detalhes, mas o básico é que, ao 'mesclar' duas ramificações por meio da interface do usuário, você verá uma opção 'resolver conflitos' que o levará a um editor, permitindo que você lide com esses conflitos de mesclagem.

insira a descrição da imagem aqui

maxwell
fonte
isso não está perguntando sobre o github, portanto, votei no que considero uma resposta muito ruim.
mschuett
1
@mschuett está certo, a questão é "como resolver conflitos no git", não "como resolver conflitos no github". Há uma diferença e já existem muitas pessoas que pensam que git e github são a mesma coisa; portanto, qualquer coisa que propague esse sentimento está errada.
Patrick Mevzek
15

Se você deseja mesclar da ramificação (teste) para o mestre, siga estas etapas:

Etapa 1 : vá para o ramo

git checkout test

Etapa 2 :

git pull --rebase origin master

Etapa 3 : se houver alguns conflitos, vá para esses arquivos para modificá-lo.

Etapa 4 : adicionar essas alterações

git add #your_changes_files

Etapa 5 :

git rebase --continue

Etapa 6 : se ainda houver conflito, volte para a etapa 3 novamente. Se não houver conflito, faça o seguinte:

git push origin +test

Etapa 7 : E então não há conflito entre teste e mestre. Você pode usar a mesclagem diretamente.

Haimei
fonte
13

Eu sempre sigo as etapas abaixo para evitar conflitos.

  • git checkout master (Venha para a ramificação principal)
  • git pull (Atualize seu mestre para obter o código mais recente)
  • git checkout -b mybranch (efetue o checkout de um novo ramo e comece a trabalhar nesse ramo para que seu mestre permaneça sempre no topo do tronco.)
  • git add. AND git commit AND git push (em sua filial local após as alterações)
  • git checkout master (Volte para o seu mestre.)

Agora você pode fazer o mesmo e manter quantas filiais locais desejar e trabalhar simultaneamente. Basta fazer um checkout git na sua filial sempre que necessário.

Chetan
fonte
12

Conflitos de mesclagem podem ocorrer em diferentes situações:

  • Ao executar "git fetch" e depois "git merge"
  • Ao executar "git fetch" e depois "git rebase"
  • Ao executar o "git pull" (que é realmente igual a uma das condições mencionadas acima)
  • Ao executar o "git stash pop"
  • Ao aplicar patches git (confirmações que são exportadas para arquivos a serem transferidos, por exemplo, por email)

Você precisa instalar uma ferramenta de mesclagem compatível com o Git para resolver os conflitos. Eu pessoalmente uso o KDiff3 e achei agradável e útil. Você pode baixar a versão do Windows aqui:

https://sourceforge.net/projects/kdiff3/files/

Aliás, se você instalar o Git Extensions, há uma opção no assistente de instalação para instalar o Kdiff3.

Em seguida, configure o git configs para usar o Kdiff como sua ferramenta de fusão:

$ git config --global --add merge.tool kdiff3
$ git config --global --add mergetool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add mergetool.kdiff3.trustExitCode false

$ git config --global --add diff.guitool kdiff3
$ git config --global --add difftool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add difftool.kdiff3.trustExitCode false

(Lembre-se de substituir o caminho pelo caminho real do arquivo Kdiff exe.)

Então, toda vez que você se deparar com um conflito de mesclagem, basta executar este comando:

$git mergetool

Em seguida, ele abre o Kdiff3 e primeiro tenta resolver os conflitos de mesclagem automaticamente. A maioria dos conflitos seria resolvida espontaneamente e você precisará corrigir o restante manualmente.

Aqui está a aparência do Kdiff3:

Digite a descrição da imagem aqui

Depois que terminar, salve o arquivo e ele passará para o próximo arquivo com conflito e você fará a mesma coisa novamente até que todos os conflitos sejam resolvidos.

Para verificar se tudo foi mesclado com êxito, basta executar o comando mergetool novamente, você deve obter este resultado:

$git mergetool
No files need merging
akazemis
fonte
8

Esta resposta é adicionar uma alternativa para usuários do VIM como eu que prefere fazer tudo dentro do editor.


TL; DR

insira a descrição da imagem aqui


O Tpope criou este ótimo plugin para o VIM, chamado fugitivo . Uma vez instalado, você pode executar :Gstatuspara verificar os arquivos que possuem conflito e:Gdiff abrir o Git de uma maneira de três maneiras.

Uma vez na fusão de três maneiras, o fugitivo permitirá que você obtenha as alterações de qualquer uma das ramificações que você está mesclando da seguinte maneira:

  • :diffget //2, obtenha alterações do ramo original ( HEAD ):
  • :diffget //3, obtenha alterações do ramo mesclado:

Quando terminar de mesclar o arquivo, digite :Gwriteo buffer mesclado. O Vimcasts lançou um ótimo vídeo explicando em detalhes essas etapas.

Vicente Bolea
fonte
6

Gitlense para código VS

Você pode experimentar o Gitlense para código VS. Eles são os principais recursos:

3. Resolva facilmente conflitos.

Eu já gosto deste recurso:

insira a descrição da imagem aqui

2. Responsabilidade da linha atual.

insira a descrição da imagem aqui

3. Culpa da sarjeta

insira a descrição da imagem aqui

4. Culpa da barra de status

insira a descrição da imagem aqui

E há muitos recursos que você pode ver aqui .

Ilyas karim
fonte
5

git buscar
git checkout seu ramo
git rebase master

Nesta etapa, você tentará corrigir o conflito usando o seu IDE preferencial

Você pode seguir este link para verificar ho para corrigir o conflito no arquivo
https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/

git add
git rebase --continue o
git commit --amend
git push origin HEAD: refs / drafts / master (pressione como um rascunho)

Agora tudo está bem e você encontrará seu commit em gerrit

Espero que isso ajude todos a respeito deste assunto.

Baini.Marouane
fonte
3

Experimente o Visual Studio Code para editar, se você ainda não estiver. O que ele faz é depois de tentar mesclar (e aparecer em conflitos de mesclagem). O código VS automaticamente detecta os conflitos de mesclagem.

Isso pode ajudá-lo muito bem, mostrando quais são as alterações feitas na original e você deve aceitar incomingou

current change(ou seja, original antes de mesclar) '?.

Ajudou para mim e também pode funcionar para você!

PS: funcionará apenas se você tiver configurado o git com seu código e o Visual Studio Code.

Kailash Bhalaki
fonte
2

Uma maneira mais segura de resolver conflitos é usar o git-mediate (as soluções comuns sugeridas aqui são bastante suscetíveis a erros).

Veja este post para uma introdução rápida sobre como usá-lo.

yairchu
fonte
2

Para quem está usando o Visual Studio (2015 no meu caso)

  1. Feche seu projeto no VS. Especialmente em grandes projetos, o VS tende a surtar ao mesclar usando a interface do usuário.

  2. Faça a mesclagem no prompt de comando.

    git checkout target_branch

    git merge source_branch

  3. Em seguida, abra o projeto no VS e vá para Team Explorer -> Filial. Agora, há uma mensagem informando que a mesclagem está pendente e os arquivos conflitantes estão listados logo abaixo da mensagem.

  4. Clique no arquivo em conflito e você terá a opção de Mesclar, Comparar, Obter Origem, Obter Destino. A ferramenta de mesclagem no VS é muito fácil de usar.

Mike
fonte
Estou usando o VS Code 2017 em um projeto muito grande e não precisa fechar o projeto. Ele lida com isso muito bem :)
protoEvangelion
2

Se você estiver usando o intelliJ como IDE, tente mesclar o pai ao seu ramo,

git checkout <localbranch>
git merge origin/<remotebranch>

Ele mostrará todos os conflitos como este

A_MBPro: teste a origem da mesclagem anu $ git / mesclagem automática de src / test / java / com /.../ TestClass.java CONFLICT (conteúdo): mescla conflito em src / test / java / com /.../ TestClass.java

Agora observe que o arquivo TestClass.java é mostrado em vermelho no intelliJ. O status do git também será exibido.

Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified:   src/test/java/com/.../TestClass.java

Abra o arquivo no intelliJ, ele terá seções com

  <<<<<<< HEAD
    public void testMethod() {
    }
    =======
    public void testMethod() { ...
    }
    >>>>>>> origin/<remotebranch>

onde HEAD é alterado na ramificação local e origem / é alterado na ramificação remota. Mantenha aqui o que você precisa e remova o que não precisa. Depois que as etapas normais devem ser executadas. Isso é

   git add TestClass.java
   git commit -m "commit message"
   git push
AJC
fonte
2

Estou usando o Código Visual da Microsoft para resolver conflitos. É muito simples de usar. Eu mantenho meu projeto aberto no espaço de trabalho. Ele detecta e destaca conflitos, além disso, oferece opções de GUI para selecionar qualquer alteração que eu queira manter do HEAD ou de entrada. insira a descrição da imagem aqui

Ammar Mujeeb
fonte