Times gastam horas debatendo rebase vs. merge como se fosse questão moral. Não é. São ferramentas com trade-offs diferentes. O problema não é escolher uma. É não entender quando usar cada uma.
O que cada um faz
Merge cria um novo commit que combina o histórico de dois branches. Preserva o histórico exatamente como aconteceu, com todos os commits de feature e o commit de merge.
# merge
* merge branch 'feature' into main
|\
| * add user validation
| * create user model
|/
* main commit
Rebase reaplica os commits de um branch sobre o outro. O histórico fica linear, como se os commits tivessem sido feitos em sequência.
# rebase
* add user validation
* create user model
* main commit
Quando usar merge
Merge é a escolha correta quando:
- O branch tem múltiplos autores e o histórico de contribuição importa
- Você quer preservar o contexto de quando as mudanças aconteceram
- O branch é longo-vivo (ex: release branch que vive semanas)
- Você está trabalhando com Git Flow ou modelo similar
No GitHub/GitLab, merge via pull request é o padrão. Cria um merge commit que documenta quando o código entrou, quem revisou, e o contexto da mudança.
Quando usar rebase
Rebase é a escolha correta quando:
- O branch é curto (1-3 commits) e você quer manter o histórico limpo
- Você precisa atualizar seu branch com mudanças da main sem criar merge commits desnecessários
- O time prefere um histórico linear para navegação com
git log --oneline - Você está preparando commits para squash merge
# Atualiza branch com mudanças da main via rebase
git fetch origin
git rebase origin/main
# Se der conflito, resolve e continua
git rebase --continue
A regra de ouro: não rebase branches públicos
Rebase reescreve histórico. Se outro desenvolvedor está trabalhando no mesmo branch, rebase cria um histórico divergente que força force push e causa confusão.
Rebase apenas branches que são só seus. Se o branch é compartilhado, use merge.
Squash merge: o melhor dos dois mundos
Muitos times adotaram squash merge como padrão: os commits da feature são comprimidos em um único commit antes de merge na main.
# No GitHub, configure no repo Settings > General > Pull Requests
# ☑ Allow squash merging
# Ou via CLI:
git checkout main
git merge --squash feature-branch
git commit -m "feat(auth): add JWT refresh token rotation"
Vantagens: histórico da main fica limpo com um commit por feature. Desvantagens: o histórico detalhado da feature (decisões, discussões, tentativas) é perdido.
O fluxo que funciona na prática
# 1. Cria branch a partir da main
git checkout main && git pull
git checkout -b feature/user-validation
# 2. Trabalha, faz commits localmente
git add . && git commit -m "feat: add user model"
git commit -m "feat: add validation logic"
# 3. Antes de abrir PR, rebase na main
git fetch origin
git rebase origin/main
# 4. Resolve conflitos se houver
git rebase --continue
# 5. Abre PR: squash merge no GitHub
Isso dá o melhor dos dois mundos: rebase manter seu branch atualizado sem merge commits, e squash merge manter o histórico da main limpo.
O que não fazer
Não force push em branches compartilhados. Não rebase commits que já foram pushados e que outras pessoas estão usando. Não faça rebase interativo em branches públicos. E não discuta isso no Slack como se fosse religião. Escolha a ferramenta que funciona para o contexto do seu time.
Curtiu o conteúdo?
Construo produtos web e soluções com IA do jeito certo — arquitetura sólida, código sustentável e entrega real.
Vamos conversar