W3docs

conflitos de merge

Aprenda o que causa conflitos de merge no Git, como ler os marcadores de conflito e como resolvê-los, cancelá-los ou preveni-los.

Um conflito de merge ocorre quando o Git não consegue reconciliar automaticamente dois conjuntos de alterações. Isso acontece quando dois branches modificam as mesmas linhas do mesmo arquivo de formas diferentes, ou quando um branch exclui um arquivo que o outro branch editou. Como o Git não pode saber qual versão está correta, ele pausa o merge e transfere a decisão para você.

Esta página explica por que conflitos acontecem, como reproduzir um, como ler os marcadores que o Git insere nos seus arquivos e as diferentes formas de resolver, cancelar ou até prevenir um conflito. O comando git merge é o que combina dois branches e é onde a maioria dos conflitos surge.

O Git lida com merges melhor do que a maioria dos sistemas de controle de versão e integra as alterações automaticamente sempre que os dois lados tocam em partes diferentes de um arquivo. Um conflito, portanto, não é um erro no seu fluxo de trabalho — é o Git pedindo uma decisão humana. Quando não consegue decidir, ele marca o arquivo como conflitado e interrompe o merge para que nada seja perdido.

mergeconflicts

Quando os conflitos acontecem?

Nem todo merge gera um conflito. Saber quando um é provável ajuda a evitar surpresas:

  • Mesmas linhas editadas nos dois lados — o caso clássico. Dois branches alteram a mesma linha de example.txt de formas diferentes.
  • Um arquivo editado em um branch e excluído no outro — o Git não pode decidir se mantém as edições ou honra a exclusão.
  • Diferenças de espaços em branco, terminação de linha ou codificação — alterações que parecem idênticas ainda podem conflitar se os bytes forem diferentes.

Quando os dois branches tocam em linhas diferentes ou arquivos diferentes, o Git os mescla automaticamente sem nenhum conflito.

Interrupções comuns de merge

O Git pode parar um merge em dois pontos distintos, e os dois casos precisam de correções diferentes. É útil saber qual situação você está enfrentando.

Falha de merge ao iniciar

O Git se recusa a iniciar um merge quando alterações não confirmadas no seu diretório de trabalho ou área de staging seriam sobrescritas pelos commits recebidos. Isso não é um conflito de conteúdo — é o Git protegendo um trabalho que você ainda não confirmou. Para assumir o controle do seu estado local, use git stash (guardar as alterações temporariamente), git commit (salvá-las), git checkout ou git reset (descartá-las) e execute o merge novamente. A mensagem é semelhante a esta:

error: Your local changes to the following files would be overwritten by merge:
	example.txt
Please commit your changes or stash them before you merge.
Aborting

Falha durante o merge

Uma falha durante o merge significa que o Git começou a combinar os branches, mas encontrou um conflito de conteúdo real entre o seu branch atual e o branch que está sendo mesclado. O merge é deixado pela metade para que você possa resolvê-lo. A mensagem é semelhante a esta:

CONFLICT (content): Merge conflict in example.txt
Automatic merge failed; fix conflicts and then commit the result.

Criando um conflito de merge

Você pode reproduzir um conflito em um repositório descartável para praticar a resolução com segurança. Comece criando um repositório com um único arquivo confirmado:

mkdir test-dir
cd test-dir
git init .
echo "some content" > example.txt
git add example.txt
git commit -m "initial commit"
[master (root-commit) a45c22d] initial commit
1 file changed, 1 insertion(+)
create mode 100644 example.txt

Isso cria um diretório chamado test-dir, inicializa um repositório e confirma o example.txt com a linha some content. Agora temos um branch (master) e um arquivo. Em seguida, crie um segundo branch e altere a mesma linha — é isso que torna o conflito possível:

git checkout -b branch_to_merge
echo "completely different content to merge later" > example.txt
git commit -m "edit the content of example.txt to make a conflict"
[branch_to_merge 4221135] edit the content of example.txt to make a conflict
1 file changed, 1 insertion(+), 1 deletion(-)

git checkout -b branch_to_merge cria o branch e muda para ele. Sobrescrevemos o example.txt e confirmamos a alteração, de modo que este branch agora tem uma versão diferente dessa linha. Volte para o master e altere o mesmo arquivo de uma forma diferente:

git checkout master
Switched to branch 'master'
echo "content to add" >> example.txt
git commit -m "added content to example.txt"
[master 11ab34b] added content to example.txt
1 file changed, 1 insertion(+)

Agora os dois branches têm seus próprios commits tocando em example.txt. Execute o merge e o Git reporta o conflito que não consegue resolver sozinho:

git merge branch_to_merge
Auto-merging example.txt
CONFLICT (content): Merge conflict in example.txt
Automatic merge failed; fix conflicts and then commit the result.

Identificando conflitos de merge

Além da mensagem impressa pelo merge, git status indica exatamente quais arquivos estão conflitados, listando-os em Unmerged paths:

git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   example.txt

both modified significa que o arquivo foi alterado nos dois lados. Abra ou faça cat do arquivo para ver os marcadores de conflito que o Git inseriu:

cat example.txt
<<<<<<< HEAD
some content
content to add
=======
completely different content to merge later
>>>>>>> branch_to_merge

Leia os três marcadores assim:

  • <<<<<<< HEAD — início do conflito. Tudo abaixo dele até ======= é o conteúdo do seu branch atual (master, para onde HEAD aponta).
  • ======= — a linha divisória entre as duas versões.
  • >>>>>>> branch_to_merge — fim do conflito. As linhas entre ======= e este marcador vêm do branch que está sendo mesclado.

Para descartar todo o merge e retornar ao estado exato anterior ao início, execute git merge --abort. Você pode ler mais sobre os marcadores na página do git merge.

Resolvendo conflitos de merge

Resolvendo manualmente

Abra o arquivo conflitado no seu editor, decida qual deve ser o conteúdo final e exclua todos os três marcadores (<<<<<<<, =======, >>>>>>>). Você pode manter um lado, o outro ou uma combinação feita à mão de ambos. Por exemplo, manter os dois trechos de conteúdo resulta em:

some content
content to add
completely different content to merge later

Quando os marcadores forem removidos e o conteúdo estiver correto, adicione o arquivo ao stage com git add e confirme para finalizar o merge:

git add example.txt
git commit -m "resolve merge conflict in example.txt"

Executar git commit após um conflito cria um merge commit que une os históricos dos dois branches.

Resolvendo escolhendo um lado

Quando você simplesmente quer manter a versão de um branch inteiro de um arquivo, não precisa editar manualmente. Faça checkout do lado desejado, adicione ao stage e confirme:

git checkout --ours example.txt    # keep the version from the current branch (master)
git checkout --theirs example.txt  # keep the version from the incoming branch
git add example.txt

--ours mantém o conteúdo do seu branch atual; --theirs mantém o conteúdo do branch recebido.

Resolvendo com uma ferramenta visual

Para conflitos maiores, git mergetool abre uma ferramenta de diff lado a lado configurada para que você possa resolver os conflitos de forma interativa em vez de editar os marcadores manualmente. Execute git mergetool para percorrer todos os arquivos conflitados, ou git mergetool example.txt para um específico.

Cancelando um merge

Se você decidir que o merge foi um erro ou preferir começar de novo com uma árvore de trabalho limpa, cancele-o:

git merge --abort

Isso restaura o seu branch e o diretório de trabalho ao estado exato em que estavam antes de você executar git merge — sem marcadores, sem arquivos mesclados pela metade. Use isso sempre que o conflito for mais do que você deseja lidar no momento.

Prevenindo conflitos de merge

Conflitos são normais, mas você pode reduzir a frequência e a gravidade com que ocorrem:

  • Faça merge ou rebase a partir do branch principal com frequência para que o seu branch nunca fique muito distante dele.
  • Mantenha os commits pequenos e focados e evite reformatações abrangentes na mesma alteração que as edições de lógica.
  • Comunique-se para que duas pessoas não estejam reescrevendo o mesmo arquivo ao mesmo tempo.
  • Visualize a sobreposição com git diff antes de mesclar para ver quais linhas podem colidir.

Folha de referência de comandos

Estes são os comandos mais usados ao lidar com conflitos:

FerramentaDescrição
git statusAjuda a encontrar os arquivos conflitados.
git mergetoolAbre uma ferramenta de diff visual para resolver conflitos de forma interativa.
git diffMostra diferenças entre commits, branches ou arquivos para ajudar a identificar possíveis conflitos antes de mesclar.
git checkout --ours/--theirsSubstitui o arquivo conflitado pelo conteúdo do branch atual ou do branch recebido.
git reset --mixedRemove os arquivos do stage, mas deixa o diretório de trabalho inalterado.
git merge --abortCancela o merge atual e restaura o diretório de trabalho ao estado anterior ao início do merge.
git resetRedefine o índice para corresponder ao HEAD, ajudando a remover arquivos conflitados do stage.

Prática

Prática
Quais são os aspectos do tratamento de conflitos de merge no Git?
Quais são os aspectos do tratamento de conflitos de merge no Git?
Was this page helpful?