Git merge vs rebase: qual escolher para o seu time
Tanto o merge quanto o rebase integram as mudanças de branches, mas tratam o histórico de formas diferentes: o merge preserva o histórico como ele aconteceu e adiciona um commit de merge, enquanto o rebase reescreve seus commits sobre uma nova base e deixa o histórico linear. Regra prática: rebase para organizar seus commits ainda não publicados, merge para integrar trabalho pronto em branches compartilhadas.
Resumindo: qual a diferença entre merge e rebase
A discussão "merge vs rebase" não é sobre qual comando é melhor, e sim sobre que histórico do projeto você quer ver. Os dois comandos chegam ao mesmo código no final. O que muda é o caminho que fica registrado no log.
- Merge junta duas linhas de histórico e registra honestamente que o trabalho foi feito em paralelo. Os commits existentes não mudam; é adicionado um commit de merge com dois pais.
- Rebase reescreve seus commits como se você tivesse começado a partir da versão mais recente da branch base. O histórico vira uma linha reta, mas os commits ganham novos hashes.
A mecânica de cada comando — flags, resolução de conflitos, modo interativo — está em artigos separados. Aqui o foco é só a escolha da estratégia.
Como fica o histórico em cada caso
Situação inicial: você criou a branch feature, fez dois commits e, nesse meio-tempo, entraram dois commits de outras pessoas na main.
D---E feature
/
A---B---C---F---G main
Depois de git merge feature na main:
D---E
/ \
A---B---C---F---G---M main
Depois de git rebase main na feature e de um fast-forward da main:
A---B---C---F---G---D'---E' main
No primeiro caso, o histórico mostra que a feature foi desenvolvida em paralelo e quando ela foi integrada. No segundo, o histórico se lê como uma narrativa sequencial, mas o fato de ter havido trabalho paralelo desaparece: D' e E' são commits novos, criados no momento do rebase.
Tabela comparativa: merge vs rebase
| Critério | git merge | git rebase |
|---|---|---|
| Commits existentes | Não mudam | São recriados com novos hashes |
| Formato do histórico | Grafo ramificado com commits de merge | Linear |
| Segurança em branches compartilhadas | Sempre seguro | Perigoso para commits já publicados |
| Precisa de force push | Não | Sim, se a branch já está no servidor |
| Conflitos | Resolvidos uma vez, no commit de merge | Podem aparecer em cada commit reaplicado |
| Contexto de "de onde veio" | Preservado | Perdido |
| Reverter uma feature inteira | Um único git revert -m 1 do commit de merge | Revert de cada commit ou de um intervalo |
Facilidade com git bisect e git log | Grafo mais difícil de ler | Mais simples: uma única linha reta |
| Curva de aprendizado | Baixa | Mais alta, exige entender reescrita de histórico |
| Limpeza de commits (squash, reword) | Só --squash da branch inteira | Flexível com rebase -i |
Prós e contras do merge
Prós
- Não destrói o histórico. Tudo o que foi publicado continua no lugar. Ninguém do time vai precisar consertar nada depois da sua ação.
- O conflito é resolvido uma vez só. Mesmo que a branch tenha 30 commits, você lida com o estado final, e não com cada passo.
- O contexto é preservado. Pelo commit de merge dá para ver qual tarefa entrou na branch principal e quando, e é fácil reverter tudo de uma vez.
Contras
- Grafo poluído. Com sincronizações frequentes, o histórico se enche de commits "Merge branch 'main' into feature", e o
git log --graphvira um mapa de linhas de trem. - Commits de rascunho vão para o histórico. "wip", "fix", "mais um fix" ficam para sempre na branch principal se não forem condensados.
Prós e contras do rebase
Prós
- Histórico linear e legível. Cada commit fica no seu lugar, o
git logse lê como uma lista de mudanças e ogit bisectencontra com mais facilidade o commit que introduziu o bug. - Dá para organizar os commits antes do review: juntar, renomear, reordenar.
- Sem commits técnicos de merge gerados pela sincronização com a branch principal.
Contras
- Reescreve o histórico. Fazer rebase de uma branch compartilhada já publicada quebra o trabalho de todo mundo que a baixou.
- Exige force push em branches que estão no servidor, ou seja, disciplina e
--force-with-lease. - Conflitos repetidos. O mesmo trecho pode gerar conflito em vários commits seguidos.
- Commits intermediários podem não compilar. Depois de mudar de base, ninguém testou os commits antigos no novo contexto.
Quando usar cada um
Rebase para o seu trabalho local
Você atualiza sua branch antes de enviar — git pull --rebase. Prepara a branch para o review e quer eliminar commits de rascunho — git rebase -i. Sua feature branch pessoal ficou atrás da main — git rebase origin/main. Em todos esses casos, são reescritos commits que só você viu (ou que pertencem só a você).
Merge para branches compartilhadas e integração
Uma feature pronta entra na main ou na develop. Várias pessoas trabalham na mesma branch. É preciso integrar a branch de release de volta na principal. Aqui o importante é não mexer em commits já publicados, e o merge é a única opção correta.
Uma regra simples de escolha
Se os commits só existem na sua máquina, pode usar rebase. Se alguém já os baixou, só merge.
Fluxos comuns para o time
| Fluxo | Como funciona | Para quem |
|---|---|---|
| Só merge | Features entram com --no-ff, sincronização com git merge main | Iniciantes em Git, times que valorizam a cronologia completa e reverts simples |
| Rebase + merge | Antes de integrar, a branch é rebaseada na main, depois vem um commit de merge com --no-ff | Times que querem histórico limpo e também os limites de cada feature |
| Rebase + fast-forward | A branch é rebaseada e integrada por fast-forward; histórico totalmente linear | Times pequenos com commits atômicos e bem cuidados |
| Squash merge | Cada pull request vira um único commit na main | Times com tarefas curtas, em que o histórico detalhado da branch não importa |
No GitHub e no GitLab, esses fluxos correspondem aos botões "Create a merge commit", "Rebase and merge" e "Squash and merge". O ideal é permitir nas configurações do repositório apenas a opção escolhida, para o histórico não virar uma mistura de estilos.
Configurações que reforçam a escolha
# pull sem commits de merge desnecessários
git config --global pull.rebase true
# ou: pull só por fast-forward, senão dá erro e você decide
git config --global pull.ff only
# sempre criar commit de merge ao integrar features
git config --global merge.ff false
Cuidado com merge.ff false: ele também afeta o git pull no modo merge. Muita gente prefere não defini-lo globalmente e passar --no-ff explicitamente ao integrar uma feature.
Exemplo: a mesma tarefa nos dois estilos
Vamos a um cenário real. Você passa três dias desenvolvendo a feature de pagamento na branch feature/payment, e nesse período entram cinco tarefas de outras pessoas na main. Antes do pull request, você precisa trazer a main atualizada e conferir se tudo funciona.
Opção com merge
git switch feature/payment
git fetch origin
git merge origin/main
# conflitos resolvidos uma vez: git add, git commit
git push
A branch ganhou o commit "Merge remote-tracking branch 'origin/main' into feature/payment". O push é normal, e quem estava acompanhando a branch não percebe nada. Se você sincronizar assim todo dia, a branch terá três commits desses, e eles vão parar na main junto com a feature se a integração for feita sem squash.
Opção com rebase
git switch feature/payment
git fetch origin
git rebase origin/main
# conflitos resolvidos no caminho, commit a commit: git add, git rebase --continue
git rebase -i origin/main # opcional: juntar commits de rascunho
git push --force-with-lease
A branch parece ter sido criada hoje de manhã a partir da main atualizada, sem commits sobrando, e o revisor consegue ler as mudanças passo a passo com mais facilidade. O preço é o push forçado e a necessidade de garantir que ninguém mais esteja commitando nessa branch.
O que a main vai mostrar no final
Na integração via pull request, a diferença se mantém. O estilo merge gera um grafo com ramificações e merges de sincronização; o estilo rebase gera uma sequência limpa de commits da feature, que pode ser integrada por fast-forward ou com um único commit de merge. O código será o mesmo, desde que os conflitos sejam resolvidos da mesma forma.
Como decidir em equipe
Responda a algumas perguntas. Várias pessoas trabalham na mesma branch? Se sim, rebase está fora de questão para essa branch. Qual é a experiência do time com Git? Se há muitos iniciantes, comece com merge e squash merge, que perdoam erros. Vocês precisam da cronologia completa para auditoria e análise de incidentes? Então commits de merge das features são úteis. Um git log legível e o uso frequente de git bisect são importantes? Então ponto para o rebase e o histórico linear.
Registre a decisão no CONTRIBUTING ou no README do repositório e ative a proteção da branch principal: proibir force push, exigir pull request, definir o método de merge permitido. Uma regra garantida pelas configurações funciona muito melhor do que qualquer combinado verbal.
Equívocos comuns
- "Rebase é coisa de avançado, merge é para iniciante". Não: são ferramentas diferentes para tarefas diferentes. Desenvolvedores experientes usam as duas.
- "Commits de merge são lixo". Os de sincronização, sim, muitas vezes são ruído. Mas o commit de merge que integra uma feature é um ponto útil: por ele se enxerga e se reverte uma tarefa inteira.
- "Com rebase há menos conflitos". Os conflitos são os mesmos, porque as mesmas linhas foram alteradas. O rebase só os distribui pelos commits, enquanto o merge resolve tudo de uma vez.
- "O rebase perde commits". Os commits antigos continuam no
git refloge podem ser recuperados até o garbage collector removê-los.
Conclusão
Escolher entre merge vs rebase é escolher entre uma cronologia fiel e um histórico linear e legível. O merge é seguro e preserva o contexto; o rebase traz limpeza, mas reescreve commits. A prática mais confiável é combinar os dois: rebasear e limpar sua branch enquanto ela é só sua, e integrar o trabalho pronto nas branches compartilhadas via merge ou squash, conforme as regras do time. O essencial é combinar o fluxo e fixá-lo nas configurações do repositório. As duas estratégias e o trabalho com branches em equipe são praticados no curso de Git.
Perguntas frequentes
O que usar no git pull: merge ou rebase?
Para atualizar a branch local, o rebase é mais prático: seus commits não publicados ficam por cima dos remotos mais recentes, sem commit de merge extra. Ative com git config --global pull.rebase true.
Dá para misturar merge e rebase no mesmo projeto?
Sim, e essa é a abordagem mais comum: rebase nas suas branches, merge nas compartilhadas. O importante é que todo o time conheça a regra.
O que um iniciante deve escolher?
Comece com merge: ele não reescreve o histórico e é mais difícil quebrar algo. Aprenda rebase nas suas branches locais depois de entender reflog e force push.
A estratégia escolhida muda o código final?
Não. Com os conflitos resolvidos da mesma forma, o estado final dos arquivos é idêntico. Só muda o histórico de commits registrado.
Qual a diferença entre squash merge e rebase?
O squash merge condensa a branch inteira em um único commit novo na branch principal, enquanto o rebase reaplica cada commit separadamente. Os dois geram histórico linear, mas o squash perde o detalhamento passo a passo.
Este tema é abordado em profundidade, com prática, no curso “Git do zero ao desenvolvedor confiante”.
- Processos de Git em equipes reais: qual fluxo de trabalho escolher
- Ferramentas Avançadas: rebase, stash, cherry-pick e tags