Git rebase interativo: reorganizando commits antes de fazer push

1. O que é o rebase interativo e por que usá-lo antes do push

O rebase interativo (git rebase -i) é uma ferramenta poderosa do Git que permite reescrever o histórico de commits locais antes de enviá-los para um repositório remoto. Diferentemente do rebase comum, que simplesmente aplica commits sobre outra base, o modo interativo abre um editor onde você pode especificar ações para cada commit envolvido.

O conceito fundamental é que estamos trabalhando exclusivamente com commits que ainda não foram compartilhados via git push. Como esses commits existem apenas no repositório local, podemos reordená-los, combiná-los, editar suas mensagens ou até removê-los sem causar problemas para outros desenvolvedores.

As principais vantagens de reorganizar commits antes do push incluem:
- Histórico limpo: commits agrupados por funcionalidade, não por "tentativa e erro"
- Revisão facilitada: colegas entendem facilmente a evolução do código
- Mensagens significativas: cada commit conta uma história clara do desenvolvimento

A diferença crucial entre o rebase comum e o interativo está no controle granular. Enquanto git rebase apenas move commits para uma nova base, git rebase -i permite transformar cada commit individualmente.

2. Preparando o terreno: quando e como iniciar um rebase interativo

Antes de começar, identifique quais commits são elegíveis. A regra de ouro é: apenas commits que não foram enviados ao remoto. Use git log --oneline para visualizar o histórico local:

$ git log --oneline
a1b2c3d (HEAD -> feature/login) Adiciona validação de email
e4f5g6h Corrige estilo do botão de login
i7j8k9l Ajusta mensagem de erro
m0n1o2p Refatora função de autenticação
q3r4s5t (main) Versão inicial do projeto

Para iniciar o rebase interativo nos últimos 4 commits (todos locais), use:

$ git rebase -i HEAD~4

Ou, alternativamente, referenciando o commit base:

$ git rebase -i q3r4s5t

O editor será aberto com uma lista como esta:

pick a1b2c3d Adiciona validação de email
pick e4f5g6h Corrige estilo do botão de login
pick i7j8k9l Ajusta mensagem de erro
pick m0n1o2p Refatora função de autenticação

Cada linha representa um commit, e a palavra pick é a ação padrão que mantém o commit inalterado.

3. As operações principais do rebase interativo: pick, reword, squash, fixup

pick

Mantém o commit exatamente como está, preservando sua mensagem e alterações. É a ação padrão para commits que você não deseja modificar.

reword

Permite alterar apenas a mensagem do commit, sem modificar seu conteúdo. Útil para corrigir erros de digitação ou melhorar descrições:

pick a1b2c3d Adiciona validação de email
reword e4f5g6h Corrige estilo do botão de login
pick i7j8k9l Ajusta mensagem de erro
pick m0n1o2p Refatora função de autenticação

squash e fixup

Ambos combinam múltiplos commits em um único. A diferença está na mensagem final:
- squash: combina as mensagens, permitindo editar o resultado
- fixup: descarta a mensagem do commit sendo combinado, mantendo apenas a do commit anterior

Exemplo prático: unindo commits de ajustes:

pick a1b2c3d Adiciona validação de email
squash e4f5g6h Corrige estilo do botão de login
fixup i7j8k9l Ajusta mensagem de erro
pick m0n1o2p Refatora função de autenticação

Resultado: teremos 3 commits finais, sendo que o primeiro incorpora as alterações dos commits e4f5g6h e i7j8k9l com uma mensagem editável.

4. Reordenando e removendo commits com segurança

Para reordenar commits, simplesmente mova as linhas no editor. Por exemplo, para colocar a refatoração antes da validação:

pick m0n1o2p Refatora função de autenticação
pick a1b2c3d Adiciona validação de email

Para remover commits desnecessários, use drop ou simplesmente delete a linha:

pick a1b2c3d Adiciona validação de email
drop i7j8k9l Ajusta mensagem de erro
pick m0n1o2p Refatora função de autenticação

Cuidado com dependências: se o commit que você moveu depende de alterações de outro commit que ficou para trás, podem ocorrer conflitos. Por exemplo, se m0n1o2p usa uma função criada em a1b2c3d, reordená-los causará erro. Sempre analise as dependências lógicas entre os commits.

5. Editando commits no meio do histórico com edit

A ação edit pausa o rebase em um commit específico, permitindo modificar arquivos. O fluxo típico é:

  1. Marque o commit com edit:
edit a1b2c3d Adiciona validação de email
pick m0n1o2p Refatora função de autenticação
  1. Após salvar e fechar o editor, o Git para no commit a1b2c3d. Faça as alterações necessárias nos arquivos.

  2. Adicione as mudanças e atualize o commit:

$ git add .
$ git commit --amend
  1. Continue o rebase:
$ git rebase --continue

Casos de uso comuns:
- Corrigir um bug introduzido em um commit antigo
- Adicionar um arquivo que foi esquecido em um commit específico
- Alterar a implementação de uma funcionalidade sem criar novos commits

6. Lidando com conflitos durante o rebase interativo

Conflitos surgem quando commits reordenados ou editados criam inconsistências no código. Por exemplo, se você moveu um commit que adiciona uma função para antes do commit que define uma variável que essa função utiliza.

Quando um conflito ocorre, o Git pausa o rebase e exibe:

$ git rebase --continue
error: could not apply a1b2c3d... Adiciona validação de email
Resolve all conflicts manually, mark them as resolved with "git add", and run "git rebase --continue".

Estratégia de resolução:

  1. Abra os arquivos conflitantes e resolva manualmente as diferenças
  2. Marque como resolvido:
$ git add arquivo-resolvido.js
  1. Continue o rebase:
$ git rebase --continue

Se a situação ficar complicada, você pode abortar tudo e retornar ao estado original:

$ git rebase --abort

7. Boas práticas e armadilhas comuns

Nunca faça rebase em commits já enviados ao remoto

Esta é a regra mais importante. Se outros desenvolvedores já têm seus commits, reescrever o histórico causará divergências e dores de cabeça. Use rebase interativo antes do git push.

Crie um branch de backup

Antes de iniciar um rebase complexo, crie um branch de segurança:

$ git branch backup-feature-login

Se algo der errado, você pode retornar facilmente:

$ git reset --hard backup-feature-login

Verifique o resultado final

Após o rebase, compare com o branch original:

$ git log --oneline --graph --all

Isso ajuda a visualizar se a reorganização ficou como esperado.

Evite rebase excessivo em branches colaborativos

Se várias pessoas trabalham no mesmo branch, o rebase frequente pode causar confusão. Prefira branches individuais e faça rebase apenas antes de mesclar.


Referências