Amend: corrigindo o último commit

1. O que é o git commit --amend?

O comando git commit --amend é uma ferramenta do Git que permite modificar o commit mais recente do branch atual. Diferente de um commit normal que adiciona um novo ponto no histórico, o amend substitui o último commit por um novo, reescrevendo o histórico local.

Quando você executa git commit --amend, o Git pega o conteúdo do último commit (arquivos e mensagem), permite que você faça alterações, e cria um novo commit com um hash SHA completamente diferente. O commit original é descartado do histórico local.

É fundamental entender que amend não é uma edição — é uma substituição. O commit antigo deixa de existir no seu repositório local, embora permaneça acessível via git reflog por um período.

2. Corrigindo a Mensagem do Commit

O uso mais comum do amend é corrigir a mensagem de um commit recente. Se você digitou "Corrige bug no modolo de pagamento" em vez de "Corrige bug no módulo de pagamento", pode corrigir rapidamente.

Sintaxe básica com -m:

git commit --amend -m "Corrige bug no módulo de pagamento"

Editando no editor padrão (sem -m):

git commit --amend

Isso abre o editor configurado (Vim, Nano, VS Code) com a mensagem atual. Você pode editá-la e salvar. O Git então cria um novo commit com a mensagem corrigida.

Exemplo prático:

$ git log --oneline -3
a1b2c3d (HEAD -> main) Adiciona funcionalidade de login
e4f5g6h Corrige validação de email
i7j8k9l Configura banco de dados

$ git commit --amend -m "Adiciona funcionalidade de login com autenticação JWT"
[main 9a8b7c6] Adiciona funcionalidade de login com autenticação JWT
 Date: Mon Oct 21 14:30:00 2024 -0300
 1 file changed, 15 insertions(+)

$ git log --oneline -3
9a8b7c6 (HEAD -> main) Adiciona funcionalidade de login com autenticação JWT
e4f5g6h Corrige validação de email
i7j8k9l Configura banco de dados

Boas práticas: Use amend para corrigir mensagens apenas em commits que ainda não foram compartilhados. É uma ótima ferramenta para polir mensagens antes de um push.

3. Adicionando Arquivos Esquecidos ao Último Commit

Outro cenário comum: você fez git commit mas esqueceu de incluir um arquivo importante. Em vez de criar um novo commit separado, pode usar amend.

Passo a passo:

# Situação: você commitou apenas index.html, mas esqueceu style.css

$ git status
On branch main
Untracked files:
  style.css

# Adicione o arquivo esquecido
$ git add style.css

# Use amend com --no-edit para manter a mensagem original
$ git commit --amend --no-edit
[main 7d8e9f0] (mesma mensagem do commit anterior)
 Date: Mon Oct 21 14:35:00 2024 -0300
 2 files changed, 50 insertions(+)

Caso de uso real:

$ git log --oneline -1
b5c4d3e Implementa formulário de contato

# Você percebeu que esqueceu de incluir o arquivo de validação
$ git add validation.js
$ git commit --amend --no-edit

$ git log --oneline -1
f6g7h8i Implementa formulário de contato

O commit agora contém tanto o formulário quanto a validação, com a mesma mensagem. O hash mudou de b5c4d3e para f6g7h8i porque um novo commit foi criado.

4. Removendo Arquivos ou Alterações do Último Commit

Às vezes você precisa remover um arquivo que foi commitado por engano. Existem duas estratégias principais:

Estratégia 1: Usando git restore --staged antes do amend

# Suponha que você commitou arquivos A, B e C, mas queria apenas A e B

# Remova C do stage
$ git restore --staged C

# Agora faça o amend sem editar a mensagem
$ git commit --amend --no-edit

Estratégia 2: Resetando e recomitando

# Volte um commit, mantendo as alterações na working directory
$ git reset HEAD~1

# Agora adicione apenas os arquivos desejados
$ git add A B

# Faça um novo commit
$ git commit -m "Mensagem original"

Cuidados importantes: Remover conteúdo já commitado pode causar perda de dados se você não tiver backup. Sempre verifique o diff antes de executar o amend:

$ git diff --cached

5. Amend e o Repositório Remoto

Este é o ponto mais crítico: nunca use amend em commits que já foram enviados para um repositório remoto compartilhado, a menos que você saiba exatamente o que está fazendo.

Quando você altera um commit com amend, o Git cria um novo hash. Se o commit original já existe no remoto, você terá históricos divergentes.

Forçando o push:

# Após um amend em commit já enviado
$ git push origin main
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs

# Solução com force-with-lease (mais seguro)
$ git push --force-with-lease origin main

Diferença entre as opções:

  • git push --force: Substitui o histórico remoto sem verificação. Perigoso.
  • git push --force-with-lease: Verifica se você tem a versão mais recente do branch remoto. Mais seguro.

Cenários aceitáveis:

  • Branches pessoais que ninguém mais usa
  • Feature branches antes de abrir um Pull Request
  • Revisões em branches de desenvolvimento compartilhado apenas com combinção da equipe

6. Amend em Commits Intermediários (Rebase Interativo)

O amend só funciona no commit mais recente. Para corrigir commits mais antigos, você precisa do rebase interativo.

Exemplo com rebase interativo:

# Corrigir o terceiro commit a partir do HEAD
$ git rebase -i HEAD~3

# No editor que abrir, você verá algo como:
pick a1b2c3d Commit 1 (mais antigo)
pick e4f5g6h Commit 2
pick i7j8k9l Commit 3 (HEAD)

# Para corrigir o Commit 2, mude 'pick' para 'edit':
pick a1b2c3d Commit 1
edit e4f5g6h Commit 2
pick i7j8k9l Commit 3

Após salvar e fechar o editor, o Git pausa no Commit 2:

Stopped at e4f5g6h... Commit 2
You can amend the commit now, with

  git commit --amend

Once you are satisfied with your changes, run

  git rebase --continue

Agora você pode fazer alterações, usar git commit --amend e depois git rebase --continue.

Diferença prática: Amend lida apenas com o último commit. Rebase interativo permite corrigir qualquer commit no histórico, mas é mais complexo e arriscado.

7. Boas Práticas e Armadilhas Comuns

Quando NÃO usar amend:

  • Em commits que já estão em branches compartilhados (main, develop)
  • Em commits que outras pessoas já baixaram ou basearam trabalho
  • Em commits que fazem parte de um Pull Request já aberto (sem avisar a equipe)

Verificando o histórico antes e depois:

# Antes do amend
$ git log --oneline -5

# Após o amend
$ git log --oneline -5

# Compare os hashes para confirmar a mudança

Recuperando o commit original com reflog:

Se você fez um amend e precisa do commit original:

$ git reflog
a1b2c3d HEAD@{0}: commit (amend): Nova mensagem
e4f5g6h HEAD@{1}: commit: Mensagem original

# Para voltar ao commit original
$ git reset --hard e4f5g6h

O git reflog mantém um registro de todos os movimentos do HEAD nos últimos 30 dias (por padrão). É sua rede de segurança para recuperar commits "perdidos" por amend.

Lista de verificação antes de usar amend:

  1. O commit já foi enviado para o remoto? Se sim, pare e avalie.
  2. Outras pessoas podem ter baseado trabalho neste commit? Se sim, não use amend.
  3. Você tem certeza do que está alterando? Execute git diff primeiro.
  4. Você sabe como recuperar o commit original se algo der errado? Lembre-se do git reflog.

Referências