git rebase
Entenda o comando git rebase, veja exemplos de uso e descubra a diferença entre o rebase padrão e o interativo.
O que o git rebase faz
Rebasing significa mover uma série de commits para um novo commit base. Em outras palavras, git rebase altera o ponto de partida do branch atual de um commit para outro, de modo que parece que o branch foi criado a partir de um ponto diferente no histórico.
O ponto fundamental a entender: o rebase não move seus commits originais. Ele cria commits totalmente novos com as mesmas alterações e mensagens de commit, mas com commits pais diferentes e, portanto, hashes de commit diferentes (SHAs). Os commits antigos tornam-se inalcançáveis, mesmo que o branch pareça igual.

Esta página abrange o rebase padrão, o rebase interativo, a forma --onto, a resolução de conflitos e como se recuperar quando um rebase dá errado.
Rebase vs. merge
Tanto git rebase quanto git merge integram alterações de um branch em outro, mas moldam o histórico de formas diferentes:
- Merge cria um novo commit de merge que une os dois históricos de branch. O histórico é não linear, mas totalmente preservado — nada é reescrito.
- Rebase reproduz seus commits no topo do branch de destino. O histórico permanece linear (sem commits de merge), mas os commits originais são reescritos.
Use o rebase quando quiser um histórico limpo e em linha reta para um branch de feature antes de compartilhá-lo. Use o merge quando quiser preservar o histórico exato de como os branches foram unidos, ou quando o branch já for público.
Rebase padrão
No modo padrão, git rebase pega os commits exclusivos do seu branch atual e os reproduz no topo de <base>. O <base> pode ser um nome de branch, uma tag ou um ID de commit.
git rebase <base>O fluxo de trabalho típico: o master avançou desde que você criou o branch, e você quer as últimas alterações do master abaixo do seu trabalho de feature sem um commit de merge.
# you are on your feature branch
git switch feature
# replay feature's commits on top of the current tip of master
git rebase masterAntes do rebase, o histórico se parece com isto (feature criado a partir de um master mais antigo):
A---B---C feature
/
D---E---F---G masterApós git rebase master, os commits de feature são recriados no topo de G:
A'--B'--C' feature
/
D---E---F---G masterA', B' e C' carregam as mesmas alterações que A, B, C, mas são novos commits com novos hashes.
Nunca faça rebase em histórico público
Nunca faça rebase em commits que já foram enviados (push) e nos quais outras pessoas podem ter baseado seu trabalho. Como o rebase substitui commits por outros novos, qualquer pessoa que tenha obtido (pull) os commits antigos verá seu histórico fora de sincronia — parecerá que parte do projeto desapareceu, e eles receberão commits duplicados ou conflitantes no próximo pull.
A regra de ouro do rebasing: só faça rebase em commits que existem exclusivamente no seu branch local e que não foram compartilhados. Fazer rebase em commits já publicados é a maneira mais comum de as equipes quebrarem os repositórios umas das outras.
O limite seguro é simples: faça rebase livremente em trabalho privado; nunca faça rebase no branch master/main compartilhado ou em qualquer branch no qual outros estão ativamente trabalhando. Esta é a mesma cautela que se aplica ao git reset e ao git commit --amend.
Rebase interativo
O modo interativo (-i, abreviação de "interactive") permite editar, reordenar, agrupar (squash) ou descartar commits individuais à medida que são reproduzidos. Esta é a ferramenta que os desenvolvedores usam para limpar um branch de feature antes de fazer o merge — combinando pequenos commits de "corrigir erro de digitação", reformulando mensagens pouco claras e descartando experimentos sem saída.
git rebase -i <base>Por exemplo, para organizar os últimos 3 commits do seu branch:
git rebase -i HEAD~3Isso abre seu editor com uma lista "todo" — uma linha por commit, do mais antigo no topo:
pick 11a1456 Add login form
pick a23db19 Fix typo in label
pick 31d332c Add password validation
# Rebase d4e5f6a..31d332c onto d4e5f6a (3 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commitPara agrupar a correção de erro de digitação no commit do formulário de login e reformular o commit de validação, você alteraria a lista para:
pick 11a1456 Add login form
fixup a23db19 Fix typo in label
reword 31d332c Add password validationSalve e feche o editor; o Git reproduz os commits aplicando cada instrução em ordem.
Comandos do rebase interativo
Cada linha na lista todo começa com um destes comandos:
pick— mantém o commit como está. Este é o padrão para cada linha.reword— mantém as alterações do commit, mas para para editar sua mensagem.edit— para neste commit para que você possa alterar seu conteúdo (dividi-lo, adicionar arquivos, etc.) e depois continuar comgit rebase --continue.squash— une este commit ao anterior e combina as duas mensagens em uma.fixup— comosquash, mas descarta a mensagem deste commit (mantém apenas a anterior).drop— remove o commit inteiramente do histórico.exec— executa um comando shell após o commit anterior (útil para rodar testes em cada etapa).
Reordenar as linhas reordena os commits; deletar uma linha é equivalente a drop.
A forma --onto
A flag --onto oferece controle preciso sobre quais commits serão movidos e para onde irão:
git rebase --onto <newbase> <oldbase> <branch>Ela pega os commits que estão em <branch> mas não em <oldbase>, e os reproduz em <newbase>. Esta é a forma de mover um branch para fora de uma base que ele não precisa mais.
Suponha que featureY foi criado a partir de featureX, mas é na verdade independente das alterações de featureX e pertence ao master:
o---o---o featureY
/
o---o---o---o featureX
/
o---o---o---o masterExecute:
git rebase --onto master featureX featureYAqui featureX é o <oldbase>, master é o <newbase>, e featureY é o branch sendo rebaseado. O Git reproduz apenas os commits próprios de featureY em master, desanexando-os de featureX:
o'--o'--o' featureY
/
o---o---o---o---o master
\
o---o---o---o featureXResolvendo conflitos durante um rebase
Como o rebase reaplica seus commits um de cada vez, um conflito pode interromper o processo em qualquer commit. Quando isso acontece, o Git faz uma pausa e informa quais arquivos estão em conflito.
O fluxo de trabalho para resolver:
# 1. fix the conflicted files in your editor, then stage them
git add <resolved-file>
# 2. continue replaying the remaining commits
git rebase --continueOutros controles enquanto um rebase está pausado:
git rebase --skip— descarta o commit atual e continua (use com cuidado; você perde as alterações desse commit).git rebase --abort— para tudo e restaura o branch exatamente como estava antes de você começar.
Um branch de longa duração que divergiu muito do master produz mais conflitos, às vezes o mesmo conflito em vários commits. Dois hábitos reduzem o problema: faça rebase contra o master frequentemente, em vez de uma única vez no final, e mantenha seus commits pequenos e focados.
Opções de configuração
Alguns padrões do rebase podem ser definidos com git config. Eles alteram o comportamento do git rebase e o que ele exibe:
rebase.stat— um boolean (padrãofalse) que ativa/desativa um diffstat visual das alterações desde o último rebase.rebase.autoSquash— um boolean que ativa/desativa o comportamento--autosquash(reordenação automática de commitsfixup!/squash!durante o rebase interativo).rebase.missingCommitsCheck— controla o que acontece quando commits são removidos da lista todo. Aceita um dos seguintes valores:
| Valor | Comportamento |
|---|---|
ignore | O padrão. Quaisquer avisos de commits ausentes são ignorados. |
warn | Um aviso é exibido no modo interativo sobre commits removidos. |
error | O rebase para e exibe mensagens de aviso sobre commits removidos. |
rebase.instructionFormat— uma string no formato git log usada para formatar cada linha de commit exibida na lista todo interativa.
Recuperando-se de um rebase malsucedido
Um rebase pode parecer destrutivo: com squash ou drop, os commits desaparecem do log do branch e parece que foram perdidos definitivamente. Não foram. O Git mantém um registro de onde seu branch apontava antes de cada operação no git reflog.
Para desfazer um rebase, encontre a entrada de logo antes dele e redefina seu branch para esse ponto:
# see where the branch was before the rebase
git reflog
# example output:
# a23db19 HEAD@{0}: rebase (finish): returning to refs/heads/feature
# 31d332c HEAD@{5}: rebase (start): checkout master
# c0ffee1 HEAD@{6}: commit: the state you want back
# move the branch back to the pre-rebase commit
git reset --hard HEAD@{6}Esta é sua rede de segurança — enquanto você puder ler o reflog, nenhum rebase é verdadeiramente irreversível.
Recuperando-se de um rebase upstream
Se um colega de equipe fizer rebase e force-push em um branch no qual você também está trabalhando, um simples git pull tentará reconciliar seus commits com a ponta remota reescrita e pode deixar você com um histórico duplicado ou confuso.
A solução usa o reflog do branch de rastreamento remoto para encontrar onde ele apontava antes do rebase e depois reproduz seu trabalho na nova ponta com --onto:
# find the old tip of origin/feature in the remote-tracking reflog
git reflog show origin/feature
# replay your local commits from the old base onto the new one
git rebase --onto origin/feature <old-origin-tip> featureIsso move apenas seus commits para a ponta do force-push, sem arrastar os commits antigos agora reescritos.
Tópicos relacionados
- git merge — a alternativa sem reescrita para integrar branches.
- git reflog — seu log de desfazer para se recuperar de um rebase malsucedido.
- git reset — move um ponteiro de branch, inclusive de volta a um estado pré-rebase.
- git cherry-pick — reproduz commits individuais sem fazer rebase de um branch inteiro.