Git merge vs rebase: qual usar e quando
A diferença entre git merge e git rebase não é opinião — é o formato do seu histórico. Entenda a regra de ouro do rebase e quando cada comando faz sentido.
O PR foi mergeado, você tenta entender o que aconteceu há três semanas, e o git log parece um diagrama de metro em hora de pico: branches se cruzando em todo lugar, merge commits com mensagem "Merge branch 'feature/x' into main" que não dizem absolutamente nada. Se você está nessa situação, provavelmente ninguém no time discutiu a diferença entre git merge e git rebase antes de começar a trabalhar.
Se você ainda está nos fundamentos do Git, o post Git para iniciantes cobre o básico antes de continuar aqui. Este post assume que você já commita, cria branches e faz push — e quer entender por que o histórico do seu projeto parece um nó.
O que cada comando realmente faz com o histórico
A diferença central não é sobre quem "ganha" — é sobre o formato do histórico que cada abordagem produz.
git merge: preserva a realidade
git merge pega dois pontos no histórico e cria um commit de merge que une os dois. O resultado é um grafo não-linear — você vê exatamente quando a branch foi criada, quando foi mergeada, e o que existia em paralelo.
# Na main, trazendo mudanças da feature
git merge feature/auth
O histórico fica assim:
A---B---C---M (main)
\ /
D---E (feature/auth)
M é o merge commit. Ele tem dois pais: C e E. O histórico mostra que D e E foram desenvolvidos em paralelo com C.
Vantagem: fidelidade. Você pode ver exatamente o que aconteceu.
Desvantagem: com muitas branches curtas, o grafo fica difícil de ler. git log --oneline começa a mostrar merge commits intercalados com commits reais.
git rebase: reescreve a história
git rebase pega seus commits e os replanta na ponta de outra branch. É como dizer: "faça de conta que eu criei minha branch a partir daqui, não de lá."
# Na feature, rebaseando em cima da main atual
git rebase main
O histórico fica assim:
A---B---C---D'---E' (main + feature rebaseada)
D' e E' são novos commits — mesmo conteúdo, mas SHA diferente. O histórico fica linear, como se o trabalho tivesse sido feito em sequência, não em paralelo.
Vantagem: histórico limpo, linear, fácil de ler no git log.
Desvantagem: você está reescrevendo o histórico. Os SHAs mudam. E aqui é onde mora o perigo.
A regra de ouro do rebase
Nunca faça rebase de uma branch que outras pessoas já têm localmente.
Isso não é sugestão — é a regra que, se quebrada, gera um tipo específico de dor que faz devs odiarem o Git.
O motivo é direto: quando você faz rebase, os commits originais (D, E) são substituídos por novos (D', E'). Se outro dev tem D e E localmente e você deu git push --force na branch rebaseada, o Git vai tentar reconciliar dois históricos incompatíveis quando ele fizer pull. O resultado é commits duplicados, conflitos estranhos e um histórico que precisa ser limpado manualmente.
# Cenário de desastre
git rebase main feature/shared # reescreve os SHAs
git push --force origin feature/shared # sobrescreve o remoto
# → colega que tinha feature/shared local agora tem problema
A regra de ouro na prática:
main,develop,staging— branches que o time inteiro usa: sempre merge, nunca rebase- sua branch de feature local, que só você está usando: rebase à vontade
Quando usar cada um
A divisão não é dogmática — é contextual.
Use merge quando:
- Você está integrando trabalho de outra pessoa na branch principal do time
- A branch teve participação de múltiplos devs
- Você quer preservar quando exatamente a feature foi concluída (útil para auditoria)
- A política do time é "histórico fiel acima de tudo"
Use rebase quando:
- Você quer atualizar sua branch de feature com as últimas mudanças da main antes de abrir o PR
- Você quer limpar uma série de commits WIP ("fix", "fix2", "agora vai") antes de submeter
- Você está trabalhando sozinho na branch e quer um histórico linear mais legível
O fluxo mais comum que funciona bem na prática:
# Trabalhando na feature, main avançou
git fetch origin
git rebase origin/main # atualiza a feature sobre a main atual
# Quando for mergear: no PR, squash merge ou merge commit
# — depende da política do time
Interactive rebase: o poder de editar o que não foi para o remoto
git rebase -i (interactive) é um recurso separado que merece menção. Ele permite reorganizar, juntar (squash), editar ou deletar commits antes de publicar.
# Editar os últimos 4 commits
git rebase -i HEAD~4
Isso abre um editor com a lista de commits. Você pode:
pick— manter o commit como estásquash(ous) — fundir com o commit anteriorreword— mudar a mensagem do commitdrop— deletar o commit
Exemplo de limpeza antes de um PR:
pick a1b2c3 feat: adiciona validação de CPF
squash d4e5f6 fix: corrige regex
squash 7a8b9c fix2: agora vai de verdade
reword 0d1e2f feat: adiciona endpoint de cadastro
Resultado: dois commits limpos, sem "fix2: agora vai de verdade" no histórico do projeto.
Isso é rebase de commits locais — exatamente o caso onde é seguro.
O caso do --force-with-lease
Se você rebaseou uma branch e precisa dar push, o Git vai recusar o push normal (porque o histórico remoto e o local divergiram). O instinto é usar git push --force, mas existe uma opção mais segura:
git push --force-with-lease origin feature/minha-branch
A diferença: --force-with-lease falha se alguém empurrou commits na branch remota desde o seu último fetch. Isso evita sobrescrever o trabalho de outra pessoa por acidente.
Se você usa --force simples numa branch compartilhada, a conversa com o time fica difícil.
Perguntas frequentes
Qual é melhor, merge ou rebase?
Depende do que você valoriza. Se quer histórico fiel que mostra o que realmente aconteceu, merge. Se quer histórico linear que seja fácil de navegar no git log, rebase na sua branch local antes de mergear. A maioria dos times usa os dois: rebase para manter branches de feature atualizadas, merge (ou squash merge) para integrar à main.
Posso fazer rebase da main na minha feature branch?
Sim, e é um uso legítimo — você está rebaseando sua branch sobre a main, não a main em si. O que não pode é fazer git rebase feature/x estando na main, reescrever os commits compartilhados, e forçar o push. O sentido do rebase importa.
O que é squash merge e por que o GitHub sugere isso?
Squash merge pega todos os commits de uma feature branch e os comprime em um único commit na main. É um meio-termo: você mantém commits livres durante o desenvolvimento (incluindo os "fix2"), mas o histórico da main permanece limpo, um commit por feature. Funciona bem para times que não querem se preocupar com disciplina de commit durante o desenvolvimento.
git rebase destrói commits?
Não exatamente — ele cria novos commits com o mesmo conteúdo e SHA diferente. Os commits originais ficam no reflog por um tempo e podem ser recuperados com git reflog se você precisar desfazer. Mas para quem tinha os commits originais em outra máquina, eles são incompatíveis com os novos.
Histórico como documento de decisão
O histórico do Git não é só pra você do futuro — é pra quem vai manter o código depois de você. Um git log limpo e descritivo é documentação. Um grafo cheio de merge commits sem contexto é ruído.
A escolha entre merge e rebase define o formato desse documento. Não existe certo absoluto — existe consistência de time. Decida a política, documente no README, e siga.
Para comparar versões de arquivos fora do Git — antes de abrir um PR ou quando você quer ver o que mudou num arquivo que não está em repositório — uso o Comparador de Texto. Você cola as duas versões e vê as diferenças destacadas lado a lado, sem precisar de terminal.
- 01 Nubank Croma: o que vem no plano, quanto custa e pra quem realmente compensa O Nubank lançou o Croma, um plano de média renda entre o cartão gratuito e o Ultravioleta. Veja o que está incluído, o cashback real, os R$ 39 de mensalidade (e como zerar) e faça a conta antes de aderir.
- 02 Como validar JSON e encontrar erros de sintaxe Trailing comma, aspas simples, chave sem fechar — os erros de sintaxe JSON mais comuns e como localizar a linha exata sem adivinhar.