Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA
LiçãoIntermediáriocódigo testado

git rebase: reescrever o histórico e quando não usar

O que muda no histórico ao rebasear, por que os hashes mudam, como resolver conflito no meio do rebase e a regra de ouro que evita estragar o repositório.

Rodolfo Mori4 min de leitura

git rebase pega commits de uma linha e reaplica suas mudanças sobre outra base. O código final pode coincidir com um merge, mas os commits reaplicados recebem hashes novos. Use para organizar trabalho local ou uma branch de tarefa; não rebase uma história que outras pessoas já puxaram sem coordenação.

O sandbox começou com dois commits na feature:

bash
git --no-pager log --oneline -3
1b1f35b feat: adiciona DDD 58c1ad9 feat: adiciona Refatoração 33d9b9f feat: cria livraria

Reaplicar significa criar novos objetos

Enquanto a feature avançava, main recebeu de8696d, uma atualização de documentação. O rebase colocou cada patch da feature depois desse commit:

bash
git rebase main
Rebasing (1/2) Rebasing (2/2) Successfully rebased and updated refs/heads/feat/catalogo.

Pense em retirar duas fichas de uma pilha e preenchê-las novamente sobre uma base atualizada. O texto da mudança pode ser igual, mas data, pai e contexto entram no hash; por isso as fichas novas têm identidades diferentes. O limite é que Git calcula patches e commits, não movimenta papéis literais.

bash
git --no-pager log --oneline -4
b287fa5 feat: adiciona DDD 452b88d feat: adiciona Refatoração de8696d docs: informa área de entrega 33d9b9f feat: cria livraria

Os hashes provam a reescrita

O teste capturou identificadores completos antes e depois:

bash
printf 'antes=%s\ndepois=%s\n' "$ANTES" "$DEPOIS"
antes=58c1ad97c71b013a9191d46f43e770ef992e0e72:1b1f35ba56e92bd5c010d20d21f3d953ff37bd7c depois=452b88da13703d40fffc47cc3a0f153c2635f1b2:b287fa57448a24cf40125b2ab36e47fecce086f9

Não há apenas abreviação diferente; são objetos diferentes. Uma branch remota que ainda aponta para os antigos enxerga a nova história como não fast-forward.

Merge preserva; rebase redesenha

Merge com divergência cria um commit com dois pais e mantém os hashes das duas linhas. Rebase produz uma sequência linear e recria os commits da branch reaplicada. Nenhum é automaticamente superior. Merge registra como o trabalho aconteceu; rebase pode simplificar a revisão de uma tarefa local.

Use merge quando a bifurcação e a integração têm valor ou quando a história é compartilhada. Use rebase para atualizar sua branch de tarefa antes do PR, quando ninguém baseou trabalho nos seus hashes. O artigo de merge mostra o grafo com dois pais.

Pull rebase evita merges acidentais de atualização

git pull --rebase faz fetch e reaplica seus commits locais sobre o upstream. Ele evita commits “merge main into minha-branch” criados apenas para atualizar. Ainda assim, inspecionar com fetch antes oferece mais controle.

bash
git fetch origin
From /tmp/grupo-git-remoto.GmCWt4/central 8eb0591..0cac5b3 main -> origin/main

Depois da inspeção, git rebase origin/main inicia a reaplicação. Um rebase sem conflito informa progresso e sucesso; um comando silencioso deve ser comprovado pelo código de saída e pelo log posterior, não por uma frase inventada.

Conflito no meio aponta qual commit falhou

Quando Refatoração e DDD entraram na mesma região, a execução real parou:

bash
git pull --rebase
Rebasing (1/1) Auto-merging catalogo.txt CONFLICT (content): Merge conflict in catalogo.txt error: could not apply 62f6095... feat: adiciona DDD hint: Resolve all conflicts manually, mark them as resolved with hint: "git add/rm <conflicted_files>", then run "git rebase --continue". Could not apply 62f6095... # feat: adiciona DDD

O Git está temporariamente em detached HEAD enquanto reaplica. Resolva o arquivo, teste, use git add e continue. --skip descarta o patch atual; só use se você comprovou que a mudança já existe ou não é desejada. --abort volta ao estado anterior ao rebase.

bash
git status --short
sed -n '1,10p' catalogo.txt
UU catalogo.txt Clean Code | 89.90 <<<<<<< HEAD Refatoração | 99.90 ======= Domain-Driven Design | 129.90 >>>>>>> 62f6095 (feat: adiciona DDD)

Continue uma decisão por vez

Depois de preservar os dois livros:

bash
git add catalogo.txt
GIT_EDITOR=true git rebase --continue
[detached HEAD 02e39a2] feat: adiciona DDD 1 file changed, 1 insertion(+) Successfully rebased and updated refs/heads/main.

Em rebase com vários commits, outro conflito pode aparecer na próxima aplicação. Não confunda repetição com falha do comando: cada patch encontra uma base nova.

Interativo organiza antes da revisão

git rebase -i BASE abre uma lista em que você pode reordenar, renomear, combinar ou editar commits. Use reword para mensagem, squash ou fixup para combinar e edit para parar. Faça uma branch de segurança e leia o log depois.

bash
git --no-pager reflog -3
02e39a2 HEAD@{0}: rebase (finish): returning to refs/heads/main 02e39a2 HEAD@{1}: rebase (continue): feat: adiciona DDD 0cac5b3 HEAD@{2}: pull --rebase (start): checkout 0cac5b37eb0d73ebd20aa722b25f597c7c0a3b30

Esse formato é o esperado do mecanismo; hashes 02e39a2 e 0cac5b3 vêm do sandbox. O reflog é a referência de recuperação descrita em desfazer no Git.

Nunca rebase o que virou base de outra pessoa

Se alguém puxou seus commits, a pessoa possui os hashes antigos. Rebase publica uma linha paralela e obriga reconciliação. Em branch pessoal de PR, o time pode aceitar atualização com git push --force-with-lease. Lease recusa quando o remote mudou desde sua última observação; --force não oferece essa proteção.

Não rebase main compartilhada. Não use force para resolver o push rejeitado sem entender quem avançou. Sua missão é rebasear dois commits num sandbox, comparar hashes completos e abortar um segundo rebase. Antes de iniciar, crie uma branch de segurança apontando para a ponta atual e anote o upstream. Depois compare o conteúdo com testes, não apenas o formato do grafo. Termine quando você justificar a operação pelo público da branch, não pela aparência linear do log. Se outra pessoa já usa os hashes, pare e combine merge ou uma janela de reescrita; a técnica nunca substitui coordenação.

  • git
  • rebase
  • historico
  • merge
  • force push

Perguntas frequentes

Rebase apaga commits?
O rebase comum reaplica mudanças como novos commits e move a branch. Os objetos antigos podem continuar acessíveis por reflog por algum tempo, mas deixam de ser a história apontada pela branch.

Dúvidas e comentários

Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.

Todo o código deste artigo foi executado em git version 2.54.0 (Apple Git-156) no macOS 27, e as saídas exibidas são as reais — como produzimos este conteúdo.

Fontes consultadas

  1. Git — git rebase — git-scm.com
  2. Pro Git — Rebasing — git-scm.com

Continue por aqui