W3docs

estratégias de merge

Aprenda as estratégias de merge do Git — ort, recursive, resolve, octopus, ours e subtree — além de fast-forward, squash e merges explícitos, com exemplos.

mergeconflicts

Estratégias de Merge do Git

Quando o seu trabalho em um branch está concluído e pronto para ser combinado com a linha principal de desenvolvimento, o Git precisa decidir como unir os dois históricos. O algoritmo utilizado para isso é chamado de estratégia de merge.

Uma estratégia de merge recebe dois (ou mais) ponteiros de branch e produz um único resultado. Na maioria das vezes, você nunca precisa nomear uma estratégia explicitamente — o comando git merge escolhe um padrão adequado com base em quantos branches você está mesclando e se os históricos divergiram. Quando você precisar de controle, passe -s <estratégia> (e opcionalmente -X <opção-de-estratégia> para ajuste fino):

git merge -s recursive feature

Esta página cobre dois conceitos relacionados que são fáceis de confundir:

  • Estratégias de merge (-s): o algoritmo que calcula a árvore mesclada — ort, recursive, resolve, octopus, ours, subtree.
  • Tipos de merge: o tipo de resultado que você obtém — um commit de merge explícito, um fast-forward ou um squash.

Você quase nunca precisa escolher uma estratégia manualmente. Os padrões estão corretos para a grande maioria dos merges; recorra a -s ou -X apenas quando encontrar um problema específico que eles resolvam.

Algoritmos de estratégia de merge

ort (padrão)

git merge -s ort feature

ort ("Ostensibly Recursive's Twin") é a estratégia de merge padrão para dois heads desde o Git 2.34 (2021). É uma reescrita mais rápida e precisa da estratégia recursive mais antiga e produz o mesmo tipo de resultado: um merge 3-way que lida com renomeações e mescla recursivamente múltiplos ancestrais comuns em um único ancestral virtual.

Por ser o padrão, você obtém ort automaticamente ao executar um merge simples:

git checkout main
git merge feature

recursive

git merge -s recursive feature

A estratégia 3-way original para mesclar dois branches, e o padrão antes do Git 2.34. Pode detectar e seguir renomeações, mas não pode usar cópias de arquivos detectadas. Raramente você precisará solicitá-la pelo nome agora — ort a substitui — mas ainda está disponível por compatibilidade.

resolve

git merge -s resolve feature

resolve realiza um único merge 3-way entre exatamente dois heads (o branch atual e o que você nomeia). Não tenta ser inteligente com múltiplas bases de merge, o que a torna rápida e previsível, mas pode mesclar incorretamente em um histórico "criss-cross" onde dois branches foram mesclados entre si anteriormente. Use-a apenas quando o merge recursive/ort produzir um resultado que você queira verificar com um algoritmo mais simples.

octopus

git merge -s octopus topic-a topic-b topic-c

octopus é a estratégia padrão quando você mescla mais de dois branches de uma vez. Ela agrupa várias pontas de branch em um único commit de merge, o que é conveniente para unir um conjunto de branches de tópico independentes. Ela deliberadamente recusa qualquer merge que exigiria resolução manual de conflitos — merges octopus devem ser limpos; se houver um conflito, você deve mesclar os branches individualmente.

ours

git merge -s ours obsolete-branch

A estratégia ours registra um commit de merge que tem o outro branch como pai, mas mantém a árvore do seu branch atual completamente inalterada — todas as alterações do outro branch são descartadas. O uso típico é marcar um branch como "mesclado" para fins históricos (para que merges futuros saibam sobre ele) enquanto ignora seu conteúdo real, por exemplo ao aposentar um branch de longa duração cujo trabalho não é mais desejado.

Aviso

Não confunda a estratégia ours (-s ours, que descarta completamente o conteúdo do outro branch) com a opção de estratégia ours (-X ours, que mantém apenas o seu lado nas linhas que realmente conflitam). Elas se comportam de forma muito diferente.

subtree

git merge -s subtree project-b

subtree é uma variante do algoritmo recursive/ort para o caso em que uma árvore é um subdiretório (uma "subárvore") da outra. Antes de mesclar, o Git desloca os caminhos de uma árvore para que as duas se alinhem e depois mescla normalmente. Este é o mecanismo por trás de incorporar um projeto em uma subpasta de outro. Para o trabalho diário com subárvores, o comando de nível mais alto git subtree geralmente é mais fácil.

Tipos de merge: como o resultado se parece

A estratégia decide como as árvores são combinadas; o tipo de merge descreve o formato do histórico que resulta.

Merge fast-forward

Quando o branch no qual você está mesclando não se moveu desde que o outro branch foi criado, não há nada a combinar — o Git pode simplesmente avançar o ponteiro do branch para o commit mais recente. Nenhum novo commit é criado e o histórico permanece perfeitamente linear. Este é o comportamento padrão do Git sempre que é possível:

git checkout main
git merge feature
# Output (when main is an ancestor of feature):
# Updating a1b2c3d..d4e5f6a
# Fast-forward
#  app.js | 3 +++
#  1 file changed, 3 insertions(+)

Para manter um registro explícito do merge mesmo quando um fast-forward é possível, force um commit de merge com --no-ff:

git merge --no-ff feature

Commit de merge explícito (3-way)

Quando ambos os branches têm novos commits — seus históricos divergiram — o Git cria um novo commit de merge com dois pais. Isso é "explícito" porque o commit é visível no histórico e registra exatamente onde e quando os branches se uniram:

git checkout main
git merge feature
# Output (when histories diverged):
# Merge made by the 'ort' strategy.
#  app.js | 5 +++++
#  1 file changed, 5 insertions(+)

Se os dois branches alteraram as mesmas linhas, o merge para com um conflito que você deve resolver manualmente — veja conflitos de merge.

Squash merge

Um squash merge recolhe todos os commits do branch de origem em um único novo commit no branch atual. Ele não cria um commit de merge e não registra o branch de origem como pai; portanto, os commits individuais do branch de origem nunca aparecem no histórico do destino:

git checkout main
git merge --squash feature
# Changes are staged but NOT committed yet:
git commit -m "Add feature X"

Isso mantém o histórico do branch principal organizado — um commit por funcionalidade — ao custo de perder o log detalhado de commits do branch de funcionalidade. É uma política popular para pull requests. Para reescrever commits dentro de um branch, veja rebase interativo.

Opções de estratégia (-X)

As estratégias ort/recursive aceitam opções extras por meio da flag -X (note o X maiúsculo, separado de -s). Por exemplo, para resolver automaticamente conflitos em favor do seu lado:

git merge -X ours feature

As opções disponíveis são:

OpçãoEfeito
oursResolve automaticamente os hunks conflitantes favorecendo o nosso lado. Alterações não conflitantes da outra árvore ainda são mescladas. (Diferente de -s ours, que descarta o outro lado completamente.)
theirsO oposto de ours: resolve conflitos automaticamente em favor da outra árvore. Não existe uma estratégia theirs separada, apenas esta opção.
patienceGasta tempo extra combinando linhas para evitar mesclagens incorretas causadas por linhas correspondentes sem importância.
diff-algorithm=<algo>Instrui o merge a usar um algoritmo de diff diferente (ex.: histogram, minimal, patience).
ignore-space-change / ignore-all-spaceIgnora diferenças apenas de espaços em branco ao detectar conflitos. Alterações de espaço em branco misturadas com alterações reais não são ignoradas.
renormalizeExecuta um check-out e check-in virtual de todos os estágios de arquivo, útil quando filtros de fim de linha ou smudge/clean foram alterados.
no-renormalizeDesativa a opção renormalize.
no-renamesDesativa a detecção de renomeações durante o merge.
find-renames=<n>Ativa a detecção de renomeações com um limiar de similaridade de n% (padrão 50%).
subtree=<path>Como a estratégia subtree, mas permite especificar o prefixo de caminho que deve ser deslocado para alinhar as árvores.

Como escolher

Para o trabalho diário, você não escolhe uma estratégia — deixe o Git usar ort, e decida apenas o resultado que deseja:

  • Quer o histórico mais simples e linear quando possível? Use apenas git merge (fast-forward automático).
  • Quer que cada merge seja registrado como um commit? Adicione --no-ff.
  • Quer um commit limpo por funcionalidade no main? Use --squash.
  • Unindo vários branches de tópico finalizados de uma vez? Um git merge a b c simples usa octopus.

Se preferir replicar seus commits sobre o branch de destino em vez de mesclar, veja git rebase. Para trazer um único commit de outro branch, use git cherry-pick.

Prática

Prática
Quais são as diferentes estratégias de merge no Git e suas características?
Quais são as diferentes estratégias de merge no Git e suas características?
Was this page helpful?