Para resolver conflitos de merge com IA com segurança, primeiro deixe o conflito legível, depois passe ao agente de código o objetivo de cada lado e regras claras, e só aceite o resultado depois que o Git confirmar que não sobrou nenhum marcador de conflito e os testes passarem. Agentes como Claude Code e Codex ajudam de verdade aqui: leem as duas versões, o ancestral comum e o código ao redor mais rápido que você, e conseguem combinar duas mudanças em vez de escolher uma. O erro típico deles é igualmente previsível: quando o objetivo de um lado não está claro, ficam com o lado que compila e descartam o outro em silêncio.
Este guia mostra por que os conflitos acontecem (e por que agentes em paralelo os tornam mais frequentes), um fluxo passo a passo do git status ao git merge --continue, um modelo de prompt, rebase versus merge, o git rerere, uma checagem antes do merge e como evitar a maioria dos conflitos. Os comandos do Git foram conferidos na documentação oficial em git-scm.com em outubro de 2026.
Por que os conflitos de merge acontecem
Ao fazer o merge de duas branches, o Git compara cada uma com o ancestral comum. Mudanças em partes diferentes de um arquivo são combinadas automaticamente. Se os dois lados mudaram a mesma região, o Git não tem como escolher: ele para e grava as duas versões no arquivo, entre marcadores de conflito. Isso é um conflito textual.
Os tipos mais comuns:
- Conflito de conteúdo: as duas branches editaram as mesmas linhas do mesmo arquivo.
- Modificação/exclusão: uma branch alterou um arquivo que a outra apagou ou moveu.
- Arquivos gerados: lockfiles, snapshots, saídas de build ou pacotes de tradução que as duas branches regeraram.
Existe ainda um conflito que o Git não enxerga: o semântico. Duas branches mexem em arquivos diferentes, fazem merge sem nenhum conflito e mesmo assim quebram uma à outra; por exemplo, uma muda a assinatura de uma função enquanto a outra adiciona uma nova chamada a ela. Só testes rodando sobre o resultado do merge pegam isso, como mostra o artigo sobre a fila de merge.
Por que agentes em paralelo geram mais conflitos
Vários agentes ao mesmo tempo, cada um no seu git worktree, não sobrescrevem os arquivos uns dos outros enquanto trabalham. Mas o conflito não some: ele vai para o momento do merge. Cada agente trabalha a partir da base em que começou e não vê o que os outros mudaram. Alguns arquivos atraem conflitos repetidamente:
- tabelas de rotas, configuração de injeção de dependência e outros registros onde cada feature acrescenta uma linha,
- arquivos barrel (
index.ts) e tipos compartilhados, - o
package.jsone o seu lockfile, - arquivos de tradução, changelogs e configurações.
O capricho dos agentes também atrapalha: reformatam um arquivo que só deviam tocar de leve, renomeiam um helper “de passagem” ou corrigem um aviso de lint que não tem nada a ver com a tarefa. Cada uma dessas ações aumenta a área que os dois lados mudaram.
Passo 1: pare e olhe
Quando um merge ou rebase para, descubra onde você está antes de pedir a alguém, pessoa ou agente, que conserte:
git status # qual operação, quais arquivos "both modified"
git diff --name-only --diff-filter=U # só os arquivos sem merge
--diff-filter=U seleciona os caminhos sem merge e dá uma lista limpa para entregar ao agente. Lembre também das saídas de emergência. Se o conflito for maior do que você esperava, nada está perdido ainda:
git merge --abort # volta ao estado anterior ao merge
git rebase --abort # devolve a branch para onde estava antes do rebase
A documentação do Git recomenda fazer commit ou stash das suas mudanças antes de um git merge, porque o --abort nem sempre consegue recuperar trabalho sem commit. O mesmo vale para o worktree de um agente: peça que ele faça commit do trabalho antes de você fazer merge de qualquer coisa nele.
Passo 2: mude para zdiff3 para ver a base
Por padrão, o Git mostra só os dois lados:
<<<<<<< HEAD
const timeout = config.timeout ?? 30_000;
=======
const timeout = getTimeout(config);
>>>>>>> feature/retry
Daqui não dá para saber como era a linha original, nem, portanto, o que cada lado queria. Mude o estilo de conflito para zdiff3 (disponível desde o Git 2.35; em versões mais antigas, use diff3):
git config --global merge.conflictStyle zdiff3
Agora o conflito mostra também o ancestral comum, depois do marcador |||||||:
<<<<<<< HEAD
const timeout = config.timeout ?? 30_000;
||||||| base
const timeout = config.timeout;
=======
const timeout = getTimeout(config);
>>>>>>> feature/retry
Agora dá para entender: um lado adicionou um valor padrão, o outro passou a leitura para uma função. A resolução certa provavelmente mantém as duas mudanças, por exemplo levando o valor padrão para dentro de getTimeout. Segundo a documentação do git-config, o zdiff3 é parecido com o diff3, mas tira do conflito as linhas iguais no início e no fim, o que deixa os trechos mais enxutos.
Se o merge já está em andamento, dá para recriar os marcadores de um arquivo no novo estilo:
git checkout --conflict=zdiff3 src/http/client.ts
Para o agente isso importa ainda mais do que para você. Sem a base, o modelo precisa adivinhar qual lado mudou o quê, e é na adivinhação que começa a perda silenciosa de dados.
Passo 3: dê ao agente o contexto certo
Os marcadores mostram as linhas. Mas o agente também precisa saber por que cada lado as mudou. O Git consegue mostrar o histórico dos dois lados para um arquivo:
git log --merge -p src/http/client.ts # primeiro os diffs do lado HEAD, depois os do lado MERGE_HEAD
git show :1:src/http/client.ts # ancestral comum
git show :2:src/http/client.ts # HEAD (ours)
git show :3:src/http/client.ts # MERGE_HEAD (theirs)
Acrescente o contexto humano: a descrição da tarefa ou do pull request de cada branch. Depois use um prompt mais ou menos assim:
Estamos no meio de um git merge da feature/retry na main. Estes arquivos
têm conflitos (merge.conflictStyle é zdiff3, a base está visível):
<saída de git diff --name-only --diff-filter=U>
Objetivo da main: <uma ou duas frases, ou a descrição do PR>
Objetivo da feature/retry: <uma ou duas frases, ou a descrição do PR>
Para cada arquivo em conflito:
1. Leia as seções ours, base e theirs e diga em uma linha o que cada lado
mudou em relação à base.
2. Escreva uma resolução que mantenha os dois objetivos. Se eles realmente
se contradizem, não escolha: pare e me pergunte.
3. Edite só os trechos em conflito. Nada de reformatar, renomear ou
corrigir coisas sem relação.
4. Não altere testes para fazê-los passar e não apague código que você
não entende.
Para package-lock.json / pnpm-lock.yaml: resolva só o package.json e depois
regere o lockfile com o gerenciador de pacotes.
No fim: nenhum marcador de conflito, rode a checagem de tipos e os testes e
faça um resumo por arquivo do que você manteve de cada lado. Não rode
git add, git commit nem git merge --continue.
A última linha deixa o passo final com você. O resumo por arquivo acelera a revisão: você confere cada afirmação contra o diff em vez de ler cada linha do zero.
Passo 4: um arquivo de cada vez, com regras claras
Algumas regras separam um merge limpo de uma regressão silenciosa:
- Nada de
--oursou--theirsem massa.git checkout --ours <caminho>pega um lado do arquivo inteiro e descarta o outro. Use só quando tiver certeza de que um lado deve vencer, por exemplo num arquivo gerado que você vai regerar de qualquer jeito. - Lembre da inversão no rebase. A documentação do Git observa que, durante
git rebaseegit pull --rebase,--oursé a branch sobre a qual você está fazendo o rebase e--theirsé o seu próprio trabalho sendo reaplicado. Agentes se confundem com isso com uma frequência surpreendente, então diga a eles os nomes das branches. - Arquivos gerados se regeram, não se mesclam. Lockfiles, snapshots e saídas de build devem ser criados pela própria ferramenta depois que o código-fonte estiver resolvido.
- Modificação/exclusão exige uma decisão. Se uma branch apagou um arquivo que a outra alterou, o agente deve avisar e perguntar, não restaurar nem apagar por conta própria.
- Divida conflitos grandes. Se um arquivo tem dezenas de trechos, peça ao agente que resolva e explique em partes, ou dê um passo atrás e repense a ordem dos merges.
Passo 5: verifique antes de continuar
Quando o agente diz “resolvido”, isso é uma afirmação, não uma prova. Verifique:
git diff --check # avisa sobre marcadores de conflito esquecidos (e erros de espaço em branco)
git diff # revise a resolução
pnpm typecheck && pnpm test # ou a checagem do seu projeto
O git diff --check sai com código diferente de zero se as mudanças introduzem marcadores de conflito, então é uma barreira barata que vale rodar sempre. Em versões recentes do Git, git diff AUTO_MERGE mostra só as mudanças feitas até agora para resolver os conflitos textuais, ou seja, exatamente o que o agente escreveu.
Depois finalize a operação você mesmo:
git add src/http/client.ts
git merge --continue # ou: git rebase --continue
Não aceite às cegas: sinais de alerta
| Sinal de alerta | O que costuma significar |
|---|---|
| A mudança de um dos lados simplesmente sumiu | O agente escolheu um lado em vez de combinar os dois |
| Um teste ou uma asserção mudou | A resolução quebrou o comportamento e o teste foi adaptado |
| Arquivos fora da lista de conflitos mudaram | Escopo crescendo: reformatação ou “correções” que precisam de revisão própria |
| Código aparece duplicado | Os dois lados foram mantidos como estavam, sem merge |
Marcadores ou um ======= solto num arquivo que não é código | Ninguém rodou git diff --check |
Se notar algum desses, peça ao agente que explique o trecho ou refaça o arquivo à mão. Uma revisão de código com IA do resultado do merge é um bom segundo olhar, mas não substitui rodar os testes.
Rebase ou merge quando há risco de conflito
Os dois funcionam; falham de jeitos diferentes.
| Merge | Rebase | |
|---|---|---|
| Onde você resolve | Uma vez, no commit de merge | Commit a commit, ao reaplicar cada um |
| O mesmo conflito duas vezes | Não | Possível, em vários commits |
--ours / --theirs | Sua branch / a outra branch | Invertido: branch de destino / seu trabalho |
| Histórico | Fica um commit de merge | Linear, os commits da branch são reescritos |
| Seguro em branches compartilhadas | Sim | Só se mais ninguém constrói em cima dessa branch |
Para branches de agente de vida curta que só você usa, fazer rebase frequente na main costuma ser mais prático: os conflitos aparecem cedo, enquanto ainda são pequenos. Para branches longas ou compartilhadas, use merge. Durante um rebase, git rebase --skip descarta o commit atual por completo, então use só quando tiver certeza de que não precisa dele.
Deixe o Git lembrar: rerere
Se você faz rebase da mesma branch várias vezes, vai resolver o mesmo conflito mais de uma vez. O git rerere (“reuse recorded resolution”) registra como você resolveu um conflito e repete essa resolução quando o mesmo conflito volta:
git config --global rerere.enabled true
Depois de ativado, git merge e git commit o chamam automaticamente. Comandos úteis:
git rerere status # caminhos cuja resolução será registrada
git rerere diff # como está a resolução agora
git rerere remaining # conflitos que o rerere não conseguiu resolver
git rerere forget src/http/client.ts # esquecer uma resolução registrada errada
Duas coisas valem saber. O rerere não mexe no índice: você continua revisando o resultado e fazendo o git add. Isso é bom, porque uma resolução errada se repete com a mesma precisão que uma certa. E os registros antigos são apagados pelo git rerere gc: por padrão, os não resolvidos após 15 dias e os resolvidos após 60.
Cheque os conflitos antes do merge
Para saber se vai haver conflito, você não precisa começar o merge. Desde o Git 2.38, git merge-tree --write-tree faz o merge sem tocar na árvore de trabalho nem no índice:
git merge-tree --write-tree --name-only main feature/retry
echo $? # 0 = limpo, 1 = há conflitos
Com --name-only, a seção de conflitos traz só os nomes dos arquivos. A documentação do Git recomenda confiar no código de saída, e não numa lista de arquivos vazia. É uma boa primeira tarefa para um agente antes de ele mexer em qualquer coisa: “verifique se a feature/retry faz merge na main sem conflitos e, se não fizer, liste os arquivos em conflito e o que cada lado mudou”.
Prevenção: menos conflitos com agentes em paralelo
O conflito mais barato é o que não acontece:
- Tarefas pequenas. Um agente que muda cinco arquivos entra em conflito menos que um que muda cinquenta. Divida tarefas grandes por área.
- Um dono por área. Decida qual agente pode mexer no roteador, no schema e nos tipos compartilhados, e escreva isso nas instruções de cada agente.
- Faça merge ou rebase com frequência. Uma branch que vive uma hora raramente entra em conflito; uma que vive uma semana, quase sempre.
- Nada de mudanças de passagem. Diga aos agentes para não reformatar, renomear nem corrigir nada fora da tarefa.
- Uma mudança de lockfile por vez. Deixe só uma branch adicionar dependências, ou regere o lockfile depois de cada merge.
- Uma fila de merge. As branches entram na principal uma de cada vez, sobre a ponta mais recente, com testes no resultado do merge, então até conflitos semânticos são pegos.
Para rodar agentes em pastas separadas, veja o artigo Git worktree para agentes em paralelo.
Como o AgentVera ajuda
O AgentVera é um app de desktop que roda CLIs de agentes de código, como Claude Code e Codex, lado a lado, com Git integrado. Estes recursos se ligam ao fluxo acima:
- Worktrees e painel do Git. Crie um worktree para cada feature e rode um agente nele; adicione ao stage arquivo por arquivo, faça commit, fetch, pull e push, e leia diffs no estilo do GitHub, unificados ou lado a lado.
- Avisos antecipados. Por padrão, o AgentVera roda
git fetchem segundo plano a cada 5 minutos. Quando chegam commits novos na sua branch, um banner oferece um fast-forward com um clique, ou um rebase quando os dois lados têm commits. Quando dois agentes no mesmo projeto editam o mesmo arquivo, a coordenação de agentes avisa você; para agentes em worktrees diferentes, ela indica que o merge pode dar conflito. - Posse de arquivos. Com a posse de arquivos, você atribui caminhos ou padrões glob como
src/api/**a um agente. Enquanto ele trabalha, agentes Claude Code são parados antes de editar esses arquivos e orientados a perguntar ao dono; Codex e outras CLIs recebem as regras nas instruções. - Equipe paralela. A equipe paralela (Pro) divide uma tarefa em partes, cada uma rodando no seu próprio worktree e fazendo merge numa branch de integração. Quando um merge dá conflito ou a checagem final falha, entra um agente de integração.
- Fila de merge. A fila de merge (Pro) faz o merge das branches uma de cada vez sobre a ponta mais recente da branch de destino. Um agente Claude resolve os conflitos, a checagem roda no resultado do merge com até 2 rodadas de correção, e uma branch que não dá para consertar é devolvida. Por padrão, a entrada na branch espera a sua aprovação.
Se você trabalha sozinho e numa branch de cada vez, o Git puro com zdiff3 e rerere é suficiente. Essas ferramentas compensam quando vários agentes produzem branches ao mesmo tempo.
Erros comuns
- Resolver sem a base. O estilo de conflito padrão esconde como o código era antes; ative o
zdiff3. - “Resolva os conflitos” como prompt inteiro. Sem saber o objetivo de cada branch, o agente escolhe o lado que parece mais completo.
- Deixar o agente rodar
git adde--continue. Guarde o passo final para depois dogit diff --checke dos testes. - Mesclar lockfiles à mão. Resolva o manifesto e depois regere.
- Fazer rebase de uma branch compartilhada. Todo mundo que construiu em cima dela vai ter que desembaraçar commits reescritos.
Conclusão
Resolver conflitos de merge com IA funciona quando o agente vê o quadro todo e as provas ficam com você: marcadores zdiff3 com a base, um prompt que nomeia os dois objetivos e proíbe atalhos, git diff --check e testes antes do git add, e rerere para conflitos que se repetem. O resto é prevenção: tarefas pequenas, posse clara de arquivos e branches que entram uma de cada vez.
Para experimentar isso com os seus agentes, baixe o AgentVera.