Edição Avançada de Histórico do Git: Alterando Commits e Rebase Interativo

Use git commit --amend e rebase interativo para limpar o histórico local sem interromper branches compartilhados.

Edição Avançada de Histórico do Git: Alterando Commits e Rebase Interativo

A edição avançada de histórico do Git ajuda você a limpar commits antes que eles se tornem parte do histórico compartilhado. Quando você entende como alterar commits e fazer rebase interativo, pode corrigir pequenos erros, combinar commits ruidosos e apresentar uma história mais clara para revisão de código.

A regra principal é simples: editar o histórico local é normal, mas reescrever o histórico compartilhado requer cuidado. Os comandos são poderosos porque alteram IDs de commits, não apenas mensagens de commits.

O que a Edição de Histórico do Git Realmente Altera

Cada commit do Git tem um ID baseado em seu conteúdo, metadados, commit pai, autor, data e mensagem. Se você alterar um commit ou reescrevê-lo durante um rebase, o Git cria um novo commit com um novo ID.

Isso é aceitável quando o commit existe apenas na sua máquina. É arriscado quando outras pessoas já puxaram o commit antigo. Os branches delas ainda podem apontar para o histórico antigo, enquanto o seu aponta para o histórico reescrito.

Use a edição de histórico para:

  • Corrigir um erro de digitação na mensagem do commit mais recente.
  • Adicionar um arquivo esquecido ao seu último commit local.
  • Agrupar vários commits de trabalho em andamento antes de abrir um pull request.
  • Reordenar commits locais para que alterações relacionadas sejam mais fáceis de revisar.
  • Dividir um commit local grande em commits lógicos menores.

Evite editar histórico em:

  • Branches principais.
  • Branches de release.
  • Branches de funcionalidades compartilhados usados por várias pessoas.
  • Qualquer branch com tags de implantação ou commits sensíveis a auditoria.

Antes de começar, verifique em qual branch você está e o que já foi enviado:

git status
git branch --show-current
git log --oneline --decorate -5

Se você não tiver certeza se a reescrita é segura, crie um branch de backup:

git branch backup-before-rebase

Esse branch fornece um ponto de recuperação conhecido se o rebase der errado.

Alterando o Último Commit

git commit --amend substitui o commit mais recente por um novo. É a maneira mais rápida de corrigir o último commit antes que outra pessoa dependa dele.

Para editar apenas a mensagem do commit:

git commit --amend

O Git abre seu editor com a mensagem atual. Salve a mensagem corrigida e o Git cria um commit substituto.

Para adicionar um arquivo esquecido ao último commit:

git add caminho/para/arquivo
git commit --amend --no-edit

A flag --no-edit mantém a mensagem existente. Isso é útil quando a mensagem do commit já está correta e você apenas esqueceu de preparar uma alteração.

Aqui está um cenário comum. Você faz commit de uma atualização de Dockerfile e depois percebe que esqueceu a alteração relacionada ao .dockerignore:

git add Dockerfile
git commit -m "Melhorar cache de build Docker"
git add .dockerignore
git commit --amend --no-edit

Agora o branch tem um commit limpo em vez de um segundo commit que diz "arquivo esquecido." Isso facilita a revisão.

Se o commit original já foi enviado, o branch remoto ainda tem o ID do commit antigo. Enviar o commit alterado requer uma atualização forçada:

git push --force-with-lease

Prefira --force-with-lease em vez de --force. Ele se recusa a sobrescrever o branch remoto se outra pessoa enviou novo trabalho desde sua última busca.

Limpando Vários Commits com Rebase Interativo

O rebase interativo permite editar vários commits de uma vez. Você escolhe um intervalo, e o Git abre uma lista de tarefas onde você pode selecionar, reformular, agrupar, corrigir, reordenar ou parar em commits.

Para editar os últimos cinco commits:

git rebase -i HEAD~5

Você verá uma lista como esta:

pick a1b2c3d Adicionar script de implantação
pick b2c3d4e Corrigir erro de digitação
pick c3d4e5f Adicionar verificação de saúde
pick d4e5f6a Atualizar documentação
pick e5f6a7b Ajustar timeout

Altere o comando no início de cada linha para controlar o que acontece. Escolhas comuns são:

  • pick: manter o commit como está.
  • reword: manter as alterações, mas editar a mensagem.
  • squash: combinar este commit com o anterior e editar a mensagem combinada.
  • fixup: combinar este commit com o anterior e descartar a mensagem deste commit.
  • edit: parar neste commit para que você possa alterar seu conteúdo.
  • drop: remover o commit.

Por exemplo, se "Corrigir erro de digitação" pertence a "Adicionar script de implantação", altere a segunda linha:

pick a1b2c3d Adicionar script de implantação
fixup b2c3d4e Corrigir erro de digitação
pick c3d4e5f Adicionar verificação de saúde
pick d4e5f6a Atualizar documentação
pick e5f6a7b Ajustar timeout

Salve e feche o editor. O Git reproduz os commits e combina a correção do erro de digitação no commit anterior.

O rebase interativo também é útil para melhorar mensagens de commits antes de um pull request. Se três commits dizem "atualizar", use reword e transforme-os em mensagens que expliquem a alteração real.

Se aparecer um conflito, resolva-o como um conflito de merge normal:

git status
git add arquivo-resolvido
git rebase --continue

Se você decidir que o rebase não vale a pena:

git rebase --abort

Isso retorna seu branch ao estado anterior ao início do rebase.

Dividindo um Commit Durante o Rebase

Às vezes, um commit contém duas alterações não relacionadas. Por exemplo, você pode ter um commit que atualiza um manifesto do Kubernetes e também corrige uma seção do README. Essas alterações provavelmente deveriam ser separadas.

Inicie um rebase interativo:

git rebase -i HEAD~3

Altere pick para edit no commit que você deseja dividir. Quando o Git parar nesse commit, redefina-o mantendo as alterações em sua árvore de trabalho:

git reset HEAD^

Agora prepare e faça commit da primeira parte lógica:

git add k8s/deployment.yaml
git commit -m "Atualizar verificação de saúde da implantação"

Em seguida, prepare e faça commit da segunda parte:

git add README.md
git commit -m "Documentar comportamento da verificação de saúde"

Continue o rebase:

git rebase --continue

Isso transforma um commit amplo em dois commits focados. Os revisores podem entender cada alteração sem separar mentalmente trabalhos não relacionados.

Quando Pedir Ajuda Antes de Reescrever

Peça ajuda antes de reescrever qualquer branch que outras pessoas usem. Um líder de equipe, engenheiro de release ou mantenedor de repositório pode informar se o branch é seguro para reescrever e como a equipe lida com pushes forçados.

Peça ajuda imediatamente se um rebase afetar commits que já foram implantados, marcados com tags ou referenciados por relatórios de incidentes. Nesses casos, preservar o histórico é frequentemente mais importante do que torná-lo organizado.

Para branches de funcionalidades rotineiros, a edição de histórico é uma etapa de limpeza normal. Use git commit --amend para o commit mais recente, rebase interativo para uma pequena série local e --force-with-lease quando precisar atualizar um branch remoto que você possui.