Aprenda / Git e controle de versão

IntermediárioAula 8 de 1416 min0% da trilha

Rebase interativo: reescrevendo commits antes de compartilhar

merge preserva o histórico exatamente como aconteceu; rebase reescreve — e isso é ótimo até você pushar.

Você trabalhou numa feature por dois dias e o git log mostra 14 commits: "wip", "funciona parcial", "corrige typo", "tenta de novo"... Isso é normal enquanto você trabalha sozinho na branch. O problema é abrir um PR assim — quem revisa não devia precisar entender sua história de tentativa e erro, só o resultado final. Rebase interativo é a ferramenta pra limpar isso antes de compartilhar.

merge vs. rebase: dois jeitos de trazer commits

git merge junta duas branches criando (na maioria dos casos) um commit de merge novo — o histórico das duas linhas do tempo fica preservado exatamente como aconteceu, lado a lado. git rebase faz outra coisa: pega os commits da sua branch e os "reaplica" em cima da ponta atual de outra branch, como se você tivesse começado a trabalhar a partir dali — o resultado é um histórico linear, sem bifurcação.

terminal
git checkout feature/checkout
git rebase main   # reaplica os commits da feature em cima do main atual

Nenhum dos dois é "o certo" — são ferramentas diferentes. Histórico linear (rebase) é mais fácil de ler depois; histórico com merges preserva o contexto real de quando cada branch existiu. Muitos times usam rebase pra limpar a branch local antes do PR, e squash merge (próxima lição) pra fechar o PR — assim o main nunca vê os commits intermediários de qualquer jeito.

git rebase -i — editando o passado

O modo interativo abre uma lista dos últimos N commits, e você escolhe o que fazer com cada um: manter (pick), juntar com o commit anterior (squash ou fixup), reescrever a mensagem (reword), reordenar as linhas, ou remover a linha inteira pra descartar o commit.

terminal — pegando os últimos 4 commits
git rebase -i HEAD~4
editor que abre — antes
pick a1b2c3d Adiciona formulário de checkout
pick e4f5a6b wip
pick 7c8d9e0 corrige typo
pick f0a1b2c funciona parcial, ajustando validação
editor — depois de reescrever pra squash
pick a1b2c3d Adiciona formulário de checkout
squash e4f5a6b wip
squash 7c8d9e0 corrige typo
squash f0a1b2c funciona parcial, ajustando validação

Ao salvar, o git abre outro editor pedindo a mensagem final do commit combinado — você escreve uma mensagem só, como se tivesse feito tudo num commit desde o início. O resultado: 4 commits bagunçados viram 1 commit limpo, com uma mensagem que descreve o que a mudança faz de verdade.

A regra de ouro: nunca rebase histórico já compartilhado

Rebase reescreve commits — cada commit reaplicado ganha um hash novo, mesmo que o conteúdo seja idêntico. Isso é inofensivo numa branch que só existe na sua máquina. Mas se você já deu push e outra pessoa já puxou (pull) aquela branch, rebase local + push --force depois apaga os commits antigos do remoto e substitui por versões novas com hash diferente — o histórico da outra pessoa diverge do seu, e ela vai ter conflitos difíceis de entender na próxima sincronização.

regra prática
Rebase é seguro em:
  - commits que só existem localmente, nunca pushados
  - sua própria branch de feature, antes de abrir o PR

Rebase é perigoso em:
  - main, develop, ou qualquer branch compartilhada
  - qualquer branch que outra pessoa já clonou/puxou

Exercício

Você fez 5 commits numa branch de feature que ainda não foi pushada (só existe na sua máquina). Quer transformar os 3 últimos commits num só, mantendo os 2 primeiros separados. Qual comando abre a lista de commits pra você editar?

Quiz rápido

Qual a diferença essencial entre git merge e git rebase?
Por que nunca fazer rebase numa branch que já foi pushada e que outra pessoa já puxou?