Git merge vs rebase: diferenças, exemplos e quando usar cada um
Git merge vs rebase decide como fica o histórico do seu projeto. Veja os dois no mesmo exemplo com saída real do log, aprenda a regra que evita desastres e copie um fluxo de trabalho seguro para equipes.
- Merge une duas branches com um novo commit de merge e mantém o histórico exatamente como aconteceu.
- Rebase reaplica seus commits sobre outra branch, o que dá uma linha reta, mas hashes novos.
- Nunca faça rebase de commits que outras pessoas já baixaram.
- Faça rebase da sua própria branch de funcionalidade antes de abrir um pull request e use merge ao levá-la para a branch principal.
Sua branch de funcionalidade está atrás da main e você precisa do trabalho novo. Git merge vs rebase é a escolha entre duas formas de obtê-lo, e ambas estão corretas. Elas diferem em como o histórico fica depois.
Criamos um repositório minúsculo, executamos os dois comandos e colamos a saída real abaixo, para você comparar o resultado em vez de imaginá-lo. Novo no Git? Comece pelo nosso tutorial de Git para iniciantes (em inglês).
O que git merge e git rebase fazem
git merge pega as pontas de duas branches e as combina. Se ambas têm commits novos, o Git cria um commit de merge com dois pais. Nada do que já existe é alterado.
git rebase pega os commits exclusivos da sua branch, deixa-os de lado, move sua branch para a ponta da outra e depois os reaplica um a um. Os commits reaplicados são commits novos com hashes novos, mesmo que as mudanças sejam as mesmas.
Git merge na prática
Nosso ponto de partida: commit A na main, dois commits (F1, F2) na feature e mais um commit (M1) adicionado depois à main. Agora fazemos merge da main na feature.
git switch feature
git merge main
git log --oneline --graph
* f507aab Merge main into feature
|\
| * 8842fb5 M1
* | 082cc6a F2
* | 5a71e3c F1
|/
* 8766865 A
O gráfico mostra a história real: duas linhas de trabalho que foram unidas. Os commits originais F1 e F2 mantêm seus hashes. O custo é um commit de merge extra e, em um projeto movimentado, o gráfico vira uma teia.
Git rebase na prática
Mesmo ponto de partida, mas desta vez fazemos rebase da feature sobre a main.
git switch feature
git rebase main
git log --oneline --graph
* 1ff474b F2
* bf9149e F1
* 8842fb5 M1
* 8766865 A
O histórico é uma linha reta, como se você tivesse começado depois do M1. Olhe os hashes: F1 era 5a71e3c e agora é bf9149e, e F2 passou de 082cc6a para 1ff474b. O Git os reescreveu, e é por isso que o rebase exige cuidado.
Merge vs rebase lado a lado
| Aspecto | Merge | Rebase |
|---|---|---|
| Forma do histórico | Gráfico ramificado com commits de merge | Uma linha reta |
| Commits existentes | Inalterados | Reescritos com hashes novos |
| Conflitos | Resolvidos uma vez, no commit de merge | Podem precisar de correção em cada commit reaplicado |
| Seguro em branches compartilhadas | Sim | Não |
| Melhor para | Integrar trabalho concluído na main | Atualizar sua própria branch antes da revisão |
Dica: se não conseguir decidir, pergunte quem mais tem a sua branch. Se ninguém, o rebase é seguro. Se um colega a baixou, use merge.
A regra de ouro do rebase
Não faça rebase de commits que existem fora do seu próprio repositório. Depois de um rebase, sua branch não corresponde mais à cópia do servidor, então o push exige força. Se um colega construiu trabalho sobre os commits antigos, o histórico dele agora diverge do seu, e resolver isso é doloroso.
Fazer rebase da sua branch privada de funcionalidade é aceitável. Fazer da main ou de qualquer branch usada por outros, não.
Um fluxo de trabalho seguro para equipes
Esta rotina mantém o histórico limpo sem surpreender ninguém. É também o que a maioria das equipes usa antes do pipeline de CI, como o do nosso guia de GitHub Actions CI/CD (em inglês).
git switch feature
git fetch origin
git rebase origin/main # or: git pull --rebase
# fix conflicts, then: git add <file> && git rebase --continue
git push --force-with-lease # only on your own branch
--force-with-lease se recusa a sobrescrever a branch do servidor se alguém tiver feito push desde o seu último fetch, o que um --force simples destruiria em silêncio. Quando o pull request for aprovado, faça merge dele na main.
Como desfazer um rebase ruim
Um rebase parece destrutivo, mas os commits antigos ficam por um tempo no reflog do Git, então você pode voltar atrás.
git reflog # find the commit before the rebase
git reset --hard HEAD@{5} # example position, check reflog first
Crie uma branch de backup com git branch backup antes de qualquer rebase arriscado e a recuperação vira um único comando. Rodando um banco de dados ou ferramentas em contêineres? Veja nosso tutorial de Docker para iniciantes (em inglês).
Considerações finais
Merge preserva a verdade, rebase a mantém organizada. Use rebase para atualizar sua própria branch, merge para entregá-la e nunca reescreva um histórico do qual outras pessoas dependem.
Perguntas frequentes
Qual é a diferença entre git merge e git rebase?
Merge combina duas branches com um commit de merge e mantém todos os commits existentes. Rebase move seus commits para cima de outra branch e os reescreve, o que produz um histórico linear.
Devo usar merge ou rebase?
Faça rebase da sua própria branch de funcionalidade para mantê-la atualizada e use merge ao entregá-la numa branch compartilhada como a main. Use merge sempre que outras pessoas compartilharem a branch.
O git rebase é perigoso?
É seguro em branches privadas e arriscado em compartilhadas, porque reescreve os hashes dos commits. Use uma branch de backup e o reflog para se recuperar se algo der errado.
O que faz o force-with-lease?
Ele força o push apenas se a branch remota ainda estiver onde você a viu pela última vez, para que você não sobrescreva por acidente commits novos de um colega.
O rebase apaga meus commits?
Não. Ele cria commits novos com as mesmas mudanças, e os antigos permanecem no reflog até o Git limpá-los.
Continue aprendendo (artigos em inglês)
Precisa de ajuda com testes, WordPress ou SEO?
Ajudamos equipes a entregar software melhor e a fazer seus sites crescerem. Conte no que você está trabalhando e sugeriremos um próximo passo claro.
Mais guias sobre testes, IA e desenvolvimento moderno
Gostou deste artigo? Escolha um tópico e vá direto para nossos tutoriais mais recentes.
Explicação das alucinações de IA: por que os modelos de linguagem inventam as coisas e como reduzi-las
Explicação das alucinações de IA: o que são, por que os modelos de linguagem as produzem, tipos comuns, como reduzi-las com aterramento e instruções…
Leia o artigo →DevOpsVariáveis de ambiente explicadas: arquivos .env, segredos e configuração bem feitos
Variáveis de ambiente explicadas com exemplos de Python que executamos: leitura e configuração, por que cada valor é uma string, arquivos .env, hera…
Leia o artigo →Desenvolvimento de softwareExplicação da limitação de taxa de API: algoritmos, cabeçalhos e tratamento de erros 429
Limitação de taxa de API explicada com uma simulação que executamos: token bucket, janela fixa, janela deslizante, 429 respostas, cabeçalhos de limi…
Leia o artigo →Automação de testesZombando em Python: unittest.mock, patch e os erros que fazem os testes mentirem
Zombaria em Python com unittest.mock, testado: Mock e return_value, side_effect, patch onde um nome é usado, especificação e autospec, zombaria de d…
Leia o artigo →Teste de softwareCobertura de código explicada: cobertura de linha versus filial e o que 100% realmente significa
Cobertura de código explicada com uma execução cobertura.py real: cobertura de linha, ramal e condição, leitura de um relatório, por que 100% de cob…
Leia o artigo →Bancos de dados e SQLDELETE vs TRUNCATE vs DROP em SQL: diferenças, reversão e quando usar cada um
DELETE vs TRUNCATE vs DROP explicado com SQL testado: o que cada um remove, rollback, aciona, redefinição de identidade, velocidade e como PostgreSQ…
Leia o artigo →Bancos de dados e SQLExibições SQL explicadas: crie, use e evite as armadilhas, com exemplos
Visualizações SQL explicadas com consultas que executamos: criação de uma visualização, resultados ao vivo, ocultação de colunas, desempenho, visual…
Leia o artigo →Desenvolvimento de softwareInterface TypeScript vs tipo: diferenças reais, testadas com o compilador
Interface TypeScript versus tipo, verificada com o compilador real: o que ambos podem fazer, o que apenas um pode fazer, mesclagem de declarações, e…
Leia o artigo →Desenvolvimento de softwarePython *args e **kwargs explicados: funções flexíveis com exemplos claros
Python *args e **kwargs explicados com o código que executamos: empacotamento e descompactação, ordem dos parâmetros, argumentos somente de palavras…
Leia o artigo →Desenvolvimento de softwareFunções Python Lambda: sintaxe, usos reais e quando não usá-los
Funções lambda do Python explicadas com o código que executamos: sintaxe, classificação com chave, mapa e filtro, fechamentos, armadilha de ligação …
Leia o artigo →Inteligência artificialO que são agentes de IA? Como eles funcionam, com um loop de agente simples que você pode executar
O que são agentes de IA? Um guia simples para o loop do agente, ferramentas, memória e proteções, com um pequeno loop Python que executamos, riscos …
Leia o artigo →DevOpsMonitoramento versus observabilidade: a verdadeira diferença, com logs, métricas e rastreamentos
Explicação do monitoramento versus observabilidade: falhas conhecidas e desconhecidas, logs, métricas e rastreamentos, um passo a passo do incidente…
Leia o artigo →DevOpsDocker Volumes vs Bind Mounts: persista os dados do contêiner da maneira certa
Volumes Docker versus montagens de ligação explicadas: por que os dados do contêiner desaparecem, volumes nomeados, montagens de ligação, tmpfs, exe…
Leia o artigo →Automação de testesTDD vs BDD: principais diferenças, um recurso criado de ambas as maneiras e quando usar cada um
TDD vs BDD explicado com um recurso de desconto construído em ambos os sentidos: refatoração vermelho-verde com o código que executamos, cenários da…
Leia o artigo →Desenvolvimento de softwareGit merge vs rebase: diferenças, exemplos e quando usar cada um
Git merge vs rebase explicado com saída real do log, uma tabela comparativa, a regra de ouro do rebase e um fluxo de trabalho seguro para equipes.
Leia o artigo →Desenvolvimento de softwareList comprehension em Python: sintaxe, exemplos e quando evitar
List comprehension em Python explicada: sintaxe, filtros, if-else, laços aninhados, tempos medidos e quando um laço for comum é a melhor escolha.
Leia o artigo →Bancos de dados e SQLSQL JOIN explicado com exemplos (Inner, Left, Right, Full)
Entenda os joins SQL passo a passo com tabelas e consultas de exemplo: INNER, LEFT, RIGHT, FULL, CROSS e SELF, além de erros comuns e dicas de desem…
Leia o artigo →