roselletabuena/resolução-de-conflitos-git

Resolva conflitos de merge, rebase, cherry-pick, revert ou stash-pop corretamente — entenda o que cada lado estava tentando fazer, combine-os em vez de escolher um, verifique se o resultado compila e continue a operação.

O que é resolução-de-conflitos-git?

Esta habilidade é projetada para auxiliar desenvolvedores a resolver conflitos do Git de forma segura e inteligente. Em vez de simplesmente escolher um lado (`--ours`/`--theirs`) e descartar o trabalho de alguém, ela orienta o usuário a entender a intenção por trás de cada alteração em conflito e combiná-las adequadamente. A habilidade abrange operações como merge, rebase, cherry-pick, revert e stash-pop, e explica como o significado de `ours` e `theirs` muda dependendo do contexto (especialmente em rebases, onde é o oposto do esperado). O processo inclui etapas para identificar a operação atual, visualizar o conflito completo (incluindo o ancestral comum com `zdiff3`), resolver combinando alterações (com diretrizes específicas para diferentes tipos de conflito), verificar o resultado com testes e build, e continuar a operação. A habilidade também fornece guardrails importantes, como nunca resolver descartando um lado por completo e nunca abortar uma operação sem motivo válido.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/roselletabuena/skills/tree/HEAD/plugins/git-workflows/skills/git-conflict-resolution

Installed? Explore more Programação e Desenvolvimento skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Resolvendo conflitos

Um conflito significa que o git encontrou duas alterações no mesmo lugar e se recusa a adivinhar. Uma resolução é uma decisão sobre a intenção, e o padrão seguro é manter a intenção de ambos os lados. Resolver excluindo um lado faz os marcadores desaparecerem e piora o problema: a compilação ainda passa, e a alteração de um colega desaparece.

1. Saiba em qual operação você está — ours e theirs dependem disso

git status                  # "rebase in progress" / "You have unmerged paths" / "cherry-pick in progress"
OperaçãoLado --ours / HEADLado --theirs
mergeo branch em que você estáo branch sendo mesclado
rebaseo branch para o qual você está fazendo rebase (upstream)seu próprio commit sendo reproduzido
cherry-pick, revert, stash popo branch em que você estáo commit sendo aplicado

A linha do rebase é a armadilha. Durante git rebase main, "ours" é main e "theirs" é o trabalho do próprio usuário, o inverso de um merge. git checkout --theirs file em um rebase mantém sua alteração e descarta a do upstream. Releia esta tabela antes de usar qualquer flag.

2. Veja o conflito completo, não apenas os marcadores

git diff --name-only --diff-filter=U        # arquivos não mesclados
git status                                   # o tipo: both modified / deleted by us / both added
git config merge.conflictStyle zdiff3        # mostra o ancestral comum também (git 2.35+; use diff3 em versões antigas)
git checkout --conflict=zdiff3 -- <file>     # re-renderiza UM arquivo com a base visível (descarta edições já feitas nele)

Com a base visível, os marcadores têm três partes: seu lado, o original, o lado deles. A maioria dos conflitos aparentes se torna óbvia quando você pode ver do que cada lado mudou a partir de.

Para entender por que cada lado mudou:

git log --merge -p -- <file>                 # commits de ambos os lados tocando o arquivo (merge ou rebase em andamento)
git show REBASE_HEAD                          # durante um rebase: o commit sendo reproduzido
git show :1:<file>  :2:<file>  :3:<file>     # base, "ours", "theirs" como arquivos completos

Leia as mensagens de commit. Uma resolução que você não consegue explicar em uma frase por lado é um palpite.

3. Resolva combinando

  • Ambos os lados editaram as mesmas linhas por razões diferentes — escreva a versão que faz ambos. Por exemplo, um lado adicionou um parâmetro tax_rate e o outro um parâmetro discount: a função resolvida recebe ambos e aplica ambos.
  • Um lado moveu ou renomeou, o outro editou — aplique a edição no novo local. Não mantenha o arquivo antigo e o novo.
  • Excluído por um lado, modificado pelo outro — esta é uma decisão real, não mecânica. Descubra por que foi excluído; se a modificação ainda importa, ela deve ser transportada, caso contrário a exclusão vence. Pergunte ao usuário se não estiver claro.
  • Arquivos gerados e lockfiles (package-lock.json, poetry.lock, go.sum, snapshots, saída compilada) — não faça merge manual. Pegue um lado, depois regenere com a ferramenta (npm install, poetry lock, go mod tidy, o comando de snapshot).
  • Arquivos binários — não há merge; escolha um lado deliberadamente (lembre-se da tabela acima) e informe isso.

O texto pode ser mesclado de forma limpa e ainda assim estar errado: se um lado renomeou uma função e o outro adicionou uma chamada para o nome antigo, o git não vê conflito. É por isso que a etapa 4 inclui compilar.

Flags cegas escondem decisões. git checkout --ours ., -X ours / -X theirs (que resolvem cada trecho conflitante para um lado) e -s ours (que descarta o outro branch inteiramente) cada um joga trabalho fora sem olhar para ele. Use-os apenas quando o usuário pediu exatamente isso e sabe o que está sendo descartado.

4. Verifique, depois continue

git diff --check                              # falha em marcadores de conflito restantes e erros de espaço em branco
grep -rnE '^(<<<<<<<|=======|>>>>>>>)' .      # cinto e suspensórios, em arquivos que o git não verifica diff
# compile e execute os testes relevantes mais rápidos
git add <arquivos-resolvidos>

Continue com o comando correspondente. Adicione GIT_EDITOR=true onde um editor abriria, já que um editor trava em um shell não interativo:

git merge --continue            # ou: git commit --no-edit
GIT_EDITOR=true git rebase --continue
GIT_EDITOR=true git cherry-pick --continue

Um rebase reproduz commits um por um, então pode parar novamente no próximo commit. Repita o ciclo. Resolva no commit mais antigo onde um conflito aparece; commits posteriores podem ser o mesmo conflito se repetindo.

Se os testes falharem após a resolução, a falha é uma informação sobre a resolução. Não continue além dela e não "corrija" editando testes até saber de qual lado comportamento o teste está protegendo.

5. Quando parar e perguntar

Pare em vez de adivinhar quando:

  • ambos os lados mudaram a lógica de negócios de maneiras incompatíveis (duas regras fiscais diferentes, duas políticas de repetição diferentes);
  • você não consegue dizer em uma frase por que cada lado fez sua alteração;
  • a resolução faz um teste falhar e a causa não está clara.

Declare as duas intenções, diga o que você escolheria e por quê, e deixe o usuário decidir. Tudo antes de --continue é reversível: git merge --abort, git rebase --abort, git cherry-pick --abort retornam a árvore para onde começou.

Conflitos repetidos

Para um rebase longo onde o mesmo conflito ocorre novamente, ou um branch que é repetidamente mesclado e abandonado:

git config rerere.enabled true      # registra cada resolução e a reproduz na próxima vez
git rerere diff                      # o que foi registrado
git rerere forget-path <file>        # descarta uma resolução registrada que estava errada

rerere reaplica uma resolução sem perguntar, então uma resolução ruim se propaga. Após um conflito resolvido por rerere, ainda verifique o resultado.

Quando um branch é antigo e muito desatualizado, mesclar o tronco uma vez geralmente significa uma rodada de conflitos; rebase os reproduz por commit. Essa escolha é do usuário.

Barreiras de proteção

  • Nunca resolva escolhendo um lado por completo para fazer os conflitos desaparecerem. O outro lado é trabalho de alguém.
  • Não aborte um rebase que o usuário pediu para você terminar só porque é tedioso; aborte apenas se estiver dando errado, e informe isso.
  • Não faça push após resolver a menos que solicitado. Um rebase precisa de um force-push; siga git-safe-history-rewrite.
  • Relate cada arquivo em conflito: o que ambos os lados fizeram, o que você manteve e qualquer coisa que não pôde verificar.

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

Habilidades Relacionadas