trilha

Fundamentos de Programação/02 - Código que Presta/Semana 08 - Git Além do Básico5 min

Resolução de Conflitos

Perguntas-guia
  • O que os marcadores <<<<<<<, ======= e >>>>>>> significam exatamente?
  • Qual lado é "ours" e qual é "theirs" — em merge e em rebase? (a resposta inverte)
  • Como git checkout --ours/--theirs resolve conflito de arquivo binário?
  • Depois de resolver, como conferir que você não perdeu mudança de ninguém?

Conceito

Um conflito acontece quando duas linhas de desenvolvimento mudaram a mesma região de um arquivo e o git não tem critério para escolher.

Os marcadores, e o que cada um significa:

<<<<<<< HEAD          # início do "seu" lado (ours)
DO-MASTER
=======               # divisor
DA-FEATURE
>>>>>>> feature       # fim do "outro" lado (theirs)
ours e theirs INVERTEM entre merge e rebase

Esta é provavelmente a maior fonte de erro de resolução em git, e vale ter verificado.

No merge (estando em master, mergeando feature):

git checkout --ours   f.txt  ->  DO-MASTER    (a branch em que você está)
git checkout --theirs f.txt  ->  DA-FEATURE   (a branch sendo mergeada)

Intuitivo.

No rebase (estando em feature, rebaseando sobre master):

git checkout --ours   f.txt  ->  DO-MASTER    (!!!)
git checkout --theirs f.txt  ->  DA-FEATURE   (!!!)

Idêntico — e portanto invertido em relação à sua intuição. Estando em feature, --ours te dá o conteúdo do master.

A razão: o rebase faz checkout da base (master) e reaplica seus commits sobre ela. Durante a operação, o "atual" é o master, e o seu commit é o que está sendo aplicado — logo, theirs.

A regra para lembrar: ours é sempre "onde eu estou pisando", não "de quem é o trabalho". No rebase você está pisando na base.

Conflito semântico é o que não aparece: nenhum marcador, tudo compila, comportamento quebrado. Alguém renomeou uma função e você adicionou uma chamada com o nome antigo em outro arquivo; ou alguém mudou a unidade de um campo e você somou. Teste é a única defesa — o git não tem como saber (1. Teste Unitário).

Na prática

O diff3 é a melhoria de qualidade de vida mais barata do git. Compare.

Padrão (dois lados, sem contexto):

<<<<<<< HEAD
DO-MASTER
=======
DA-FEATURE
>>>>>>> feature

Com merge.conflictStyle = zdiff3 (três lados — inclui a base comum):

<<<<<<< HEAD
DO-MASTER
||||||| 647e8f2          <- a BASE COMUM (o rótulo é o sha do merge-base)
base
=======
DA-FEATURE
>>>>>>> feature

Ver a base muda tudo: você passa a saber o que cada lado alterou, em vez de adivinhar. Configure uma vez:

git config --global merge.conflictStyle zdiff3

rerere (reuse recorded resolution) grava como você resolveu cada conflito e reaplica automaticamente quando o mesmo conflito reaparecer. Isso é transformador ao rebasear uma branch longa, onde você resolve o mesmo conflito uma vez por commit:

git config --global rerere.enabled true

Respostas às perguntas-guia

1. O que os marcadores <<<<<<<, ======= e >>>>>>> significam exatamente?

<<<<<<< abre o lado ours (onde você está), ======= separa, >>>>>>> fecha o lado theirs (o que está sendo aplicado). Com zdiff3, aparece também ||||||| com a base comum.

2. Qual lado é "ours" e qual é "theirs" — em merge e em rebase? (a resposta inverte)

Operação Você está em --ours --theirs
git merge feature (em master) master master feature
git rebase master (em feature) feature master feature

Verificado nos dois casos: --ours devolveu DO-MASTER nas duas situações. ours é a base sobre a qual se aplica, não "o seu trabalho".

3. Como git checkout --ours/--theirs resolve conflito de arquivo binário?

Para binário não existe merge de conteúdo — você escolhe um arquivo inteiro:

git checkout --ours  imagem.png     # mantém a versão da base
git checkout --theirs imagem.png    # aceita a versão aplicada
git add imagem.png

Para arquivos gerados (lock files, snapshots), o correto costuma ser regenerar em vez de escolher: git checkout --theirs go.sum && go mod tidy.

4. Depois de resolver, como conferir que você não perdeu mudança de ninguém?

Em ordem:

git diff --check                    # marcador esquecido, espaço em branco
grep -rn '<<<<<<<\|>>>>>>>' .       # marcador que escapou (o pior erro)
git diff --cached                   # o que você está de fato comitando
git log --merge -p arquivo          # os commits dos DOIS lados que tocaram o arquivo
git diff HEAD...MERGE_HEAD          # o que vem do outro lado
<rodar a suíte de testes>           # a única defesa contra conflito semântico

git log --merge -p <arquivo> é o comando mais útil e menos conhecido dessa lista: ele mostra só os commits conflitantes que tocaram aquele arquivo, dos dois lados. É como você entende a intenção de cada lado antes de escolher.

Armadilhas

  • Marcador comitado. <<<<<<< no código em produção. git diff --check e um hook de pre-commit resolvem.
  • Resolver escolhendo um lado inteiro por pressa, descartando trabalho alheio sem ler. O git log --merge existe para evitar isso.
  • ours/theirs invertidos no rebase — resolver "mantendo o meu" e descartar o próprio trabalho.
  • Conflito semântico: compila, não conflita, está quebrado. Só teste pega.
  • Resolver em arquivo gerado em vez de regenerar (go.sum, package-lock.json).
  • git checkout . no meio de um conflito descarta a resolução em andamento.
  • Rebase longo = mesmo conflito repetido. Ligue rerere antes, não durante.

Comandos essenciais

git config --global merge.conflictStyle zdiff3   # mostra a BASE comum
git config --global rerere.enabled true          # grava e reaplica resoluções
git status                            # quais arquivos, em que estado
git diff --name-only --diff-filter=U  # só os arquivos em conflito
git checkout --ours  <arq>            # lado da base
git checkout --theirs <arq>           # lado sendo aplicado
git checkout --merge <arq>            # volta os marcadores (desfaz a edição)
git log --merge -p <arq>              # os commits conflitantes dos dois lados
git diff --check                      # marcador esquecido
git merge --abort                     # desiste do merge
git rebase --abort                    # desiste do rebase
git mergetool                         # ferramenta visual de 3 vias

Relacionado


Parte de Semana 08 - Git Além do Básico · 00 - MOC Fundamentos de Programação

Buscar

Busca por título, seção e texto das notas