Fundamentos de Programação/02 - Código que Presta/Semana 08 - Git Além do Básico5 min
Resolução de Conflitos
- 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/--theirsresolve 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 rebaseEsta é 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 --checke um hook de pre-commit resolvem. - Resolver escolhendo um lado inteiro por pressa, descartando trabalho alheio sem ler.
O
git log --mergeexiste para evitar isso. ours/theirsinvertidos 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
rerereantes, 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
- 1. Rebase vs Merge — a inversão de
ours/theirsnasce daqui - 2. Cherry-pick — o conflito de lado vazio que o pick produz
- 1. Teste Unitário — semana 7, a única defesa contra conflito semântico
- 4. Reflog — se a resolução der errado, o estado anterior está lá
Parte de Semana 08 - Git Além do Básico · 00 - MOC Fundamentos de Programação