Duas formas de combinar branches: fast-forward e merge de três vias

Prévia grátis 3 min de leitura

Todo branch existe para voltar a se juntar

O curso de Branching construiu uma linha de histórico a partir do main e a deixou lá de propósito. O add-discount-percentage está dois commits à frente, intocado pelo main. Um branch que nunca se junta de volta não é trabalho terminado: é um experimento que ninguém aproveitou. O git merge é como ele volta para casa.

Caso um: fast-forward

Se o main não mudou desde que o branch se separou, juntar os dois é trivial. O Git só move o ponteiro do main para frente:

Antes:   a ─▶ b (main)
               \
                c ─▶ d (feature)

Depois:  a ─▶ b ─▶ c ─▶ d (main, feature)
git switch main
git merge feature
Updating b8e3f1a..7c6b5a4
Fast-forward
 app/models/product.rb | 3 +++
 1 file changed, 3 insertions(+)

Nenhum commit novo é criado: o main vira um ponteiro para o mesmo commit que o feature já aponta. Esse é o exato mecanismo que o git pull usou lá no curso de Remotos sempre que seu branch local não tinha nada próprio.

Caso dois: merge de três vias

Em qualquer projeto ativo, o main ganha commits próprios enquanto o branch está em andamento. Aí o fast-forward é impossível. Os dois históricos divergiram e os dois precisam ser mantidos:

Antes:             e (main)
                  /
a ─▶ b ─▶ c ─▶ d
                  \
                    f ─▶ g (feature)

Depois:            e ─────────────┐
                  /                 ▼
a ─▶ b ─▶ c ─▶ d                    h (main)
                  \                 ▲
                    f ─▶ g ──────────┘
git switch main
git merge feature
Merge made by the 'ort' strategy.
 app/models/product.rb | 3 +++
 1 file changed, 3 insertions(+)

O Git cria o commit h: um commit de merge com dois pais (e e g), combinando as duas linhas de histórico em uma só. Para descobrir o que mudou em cada lado, o Git compara três commits: o ancestral comum (d, o último commit que os dois branches compartilham) e as duas pontas. Daí "três vias".

Confirmando qual tipo acabou de acontecer

git log --oneline --graph -5

Um fast-forward mostra uma única linha reta, sem bifurcação. Um merge de três vias mostra a bifurcação explicitamente, com um commit de merge juntando as linhas de volta: visualmente, justamente os diagramas acima.

Forçando um commit de merge mesmo quando fast-forward é possível

Alguns times preferem que toda feature deixe uma marca visível no histórico do main, mesmo quando um fast-forward funcionaria tecnicamente:

git merge --no-ff feature

Isso sempre cria um commit de merge, e "esse grupo de commits foi uma feature só" fica legível como unidade no log. Alguns times adotam isso como padrão; o Git não exige.

Pontos-chave

  • Um merge fast-forward só move o ponteiro do main para frente, sem commit novo. Ele só é possível quando o main não tem commits próprios desde a separação.
  • Um merge de três vias cria um commit de merge com dois pais, combinando históricos que divergiram usando o ancestral comum deles.
  • git log --oneline --graph mostra qual tipo aconteceu: uma linha reta versus uma bifurcação visível se juntando de volta.
  • git merge --no-ff força um commit de merge mesmo quando um fast-forward é possível, para times que querem os limites de feature visíveis no histórico.
Aula 1 de 7 · grátis

Continue com a aula 2

Quando o Git não consegue fazer merge automático: conflitos

Mostra como surge um conflito quando os dois lados mudam as mesmas linhas e o que o git status mostra.

Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.

Digite para buscar...