📦 Capítulo 06: Gerenciamento de Branches & Estratégias de Merging
Módulo 03: Versionamento com Git e GitHub • Bloco 2: Branches, Merges & Resolução de Conflitos
🗺️ Mapa Conceitual do Capítulo
flowchart TD
subgraph BRANCH_ANATOMY["Anatomia de Branches & Ponteiro HEAD"]
REFS["Ponteiro em .git/refs/heads/ (Arquivo Texto com Hash de 41 bytes)"]
HEAD_SYM["HEAD Simbólico (ref: refs/heads/main)"]
DETACHED["Detached HEAD (HEAD Apontando Diretamente para Hash de Commit)"]
REFS --> HEAD_SYM --> DETACHED
end
subgraph MERGE_STRATEGIES["Estratégias de Integração (Merge Engine)"]
FF["Fast-Forward (Avanço Linear do Ponteiro · Zero Novos Commits)"]
THREE_WAY["3-Way Merge (Cálculo via merge-base · Gera Commit com 2 Pais)"]
SQUASH["Squash Merge (Condensa N Commits em 1 Único Snapshot)"]
FF --> THREE_WAY --> SQUASH
end
subgraph MERGE_FLAGS["Políticas de Governança de Integração"]
FF_ONLY["--ff-only (Exige Histórico Linear Estrito no Pull/Merge)"]
NO_FF["--no-ff (Força Commit de Merge para Preservar Contexto da Feature)"]
HYGIENE["Higiene: git branch --merged & git branch -d"]
FF_ONLY --> NO_FF --> HYGIENE
end
BRANCH_ANATOMY --> MERGE_STRATEGIES
MERGE_STRATEGIES --> MERGE_FLAGS
🌿 1. A Verdadeira Natureza das Branches no Git
No imaginário popular de quem migra de sistemas legados como SVN, criar uma branch significaria duplicar gigabytes de arquivos em outra pasta do servidor. No Git, uma branch é apenas um arquivo texto plano de 41 bytes armazenado em .git/refs/heads/<nome-da-branch>:
# Conteúdo real do arquivo .git/refs/heads/main:
8a3f21cb04e792d4f58c6395379b1897c8d99f01
O Ponteiro HEAD e o Estado de Detached HEAD:
- HEAD Normal: É uma referência simbólica que aponta para a branch ativa (
ref: refs/heads/main). Quando você faz um commit, a branch avança e o HEAD a acompanha automaticamente. - Detached HEAD (HEAD Desanexado): Ocorre quando você faz checkout diretamente para um hash de commit (
git checkout a1b2c3d) ou para uma tag. Se você criar commits nesse estado, eles não pertencerão a nenhuma branch e serão eventualmente eliminados pelo Garbage Collector (git gc) se você trocar de branch sem criar um ponteiro seguro:
# Se você comitou em estado de Detached HEAD, resgate seu trabalho antes de sair:
git switch -c nova-branch-de-resgate
🔀 2. A Mecânica das Três Estratégias de Merge
Ao executar git merge <origem>, o motor do Git consulta o ancestral comum mais recente (Merge Base) via algoritmo de grafo acíclico (git merge-base target source):
1. Fast-Forward Merge (FF):
Ocorre quando o branch de destino (ex.: main) não recebeu nenhum commit novo desde que a feature ramificou. O Git simplesmente desliza o ponteiro de main até a ponta da feature.
- Vantagem: Histórico perfeitamente limpo e linear.
- Desvantagem: Perde o agrupamento histórico visual que delimita o início e fim da feature.
Antes do FF:
main: o---o (Base)
\
feature: o---o---o
Depois do git merge feature (Fast-Forward):
main: o---o---o---o---o (Ponteiro apenas avançou!)
2. Merge de 3 Vias (3-Way Merge / True Merge):
Ocorre quando ambos os branches divergiram após o ancestral comum. O Git compara três árvores: \(\text{Merge de 3 Vias} = \text{Tree Base} \oplus \text{Tree Ours (main)} \oplus \text{Tree Theirs (feature)}\)
- O Git cria automaticamente um Commit de Merge com dois pais (
Parent 1: main,Parent 2: feature).
o---o---o [feature]
/ \
o---o--o-----------o [main - Commit de Merge com 2 pais]
3. Squash Merge (git merge --squash):
Pega todas as modificações introduzidas pelos $N$ commits da feature e as aplica diretamente na Staging Area do branch destino em um único bloco.
- Permite criar um único commit conciso e descritivo em
main, descartando commits intermediários de “wip” ou “ajustes”. - Atenção: Não cria um commit de merge nem associa parentesco no DAG.
🛡️ 3. Governança de Integração: Flags --ff-only vs --no-ff
A escolha da política de merge dita como a arquitetura do repositório evolui:
# 1. Política de Histórico Linear Estrito (--ff-only):
# Se houver divergência, o comando recusa o merge e falha, exigindo rebase prévio
git merge --ff-only feature/nova-api
# 2. Política de Preservação Explícita de Features (--no-ff):
# Mesmo que o Fast-Forward seja matematicamente possível, FORÇA a criação do commit de merge
git merge --no-ff feature/nova-api -m "merge: integrar feature nova-api em main"
🧹 4. Higiene e Ciclo de Vida de Branches
Branches de curta duração devem ser eliminadas imediatamente após a integração para manter a árvore limpa:
# 1. Listar todas as branches locais que já foram totalmente integradas na branch atual
git branch --merged
# 2. Listar branches que ainda possuem commits não integrados (proteção contra perda de trabalho)
git branch --no-merged
# 3. Exclusão segura (o Git recusa deletar se a branch contiver código não integrado)
git branch -d feature/login
# 4. Exclusão forçada (Hard Delete - use apenas quando desejar descartar a branch intencionalmente)
git branch -D feature/experimento-falho