TL;DR: para desfazer o último commit mantendo as mudanças, rode git reset --soft HEAD~1 (as mudanças ficam no stage) ou git reset HEAD~1 (as mudanças ficam na sua working tree). Se o commit já foi enviado, rode git revert HEAD — ele cria um commit novo que desfaz o anterior sem reescrever o histórico. Esses três comandos cobrem quase todo momento de “commitei cedo demais”. O resto do guia passa caso por caso com comandos prontos para colar, explica a diferença entre --soft, --mixed e --hard e mostra como recuperar a situação se algo der errado. Todo comando abaixo funciona em qualquer instalação recente do Git no Linux, macOS ou Windows.
Como desfazer o último commit e manter as mudanças?
A situação mais comum: você commitou, percebeu um typo, um arquivo faltando, ou lembrou que a mudança pertencia a outro commit. Nada foi enviado. Desfaça o commit e devolva tudo ao lugar:
# O commit sai do histórico — as mudanças voltam para a área de staging
git reset --soft HEAD~1
# As mudanças voltam para a working tree (fora do stage)
git reset HEAD~1 HEAD~1 significa “um commit antes de onde o HEAD aponta agora”. Depois de qualquer um dos comandos, seus arquivos continuam intactos no disco — só o ponteiro da branch se moveu. Confirme com git status: com --soft as mudanças estão no stage, prontas para commitar de novo com as correções embutidas; sem flag elas estão fora do stage, e você pode editar à vontade antes.
Um hábito mais seguro, quando você só quer adicionar arquivos ao último commit, é não desfazê-lo:
git add forgotten-file.txt
git commit --amend --no-edit O --amend substitui o último commit no lugar (aqui, sem mudar a mensagem). Lembre que amendar um commit já enviado reescreve o histórico — volto nisso abaixo.
Qual é a diferença entre —soft, —mixed e —hard?
Essa é a parte que vale decorar, porque a flag decide para onde suas mudanças vão — e se elas podem se perder:
| Flag | Desfaz o commit? | Mudanças no disco | Mudanças no stage? | Uso típico |
|---|---|---|---|---|
--soft | Sim | Mantidas | Sim | Commitar de novo com ajustes pequenos |
--mixed (padrão) | Sim | Mantidas | Não | Reagrupar mudanças, re-stage seletivo |
--hard | Sim | Apagadas | — | Jogar o trabalho fora por completo |
git revert | Não (commit novo) | Mantidas | — | Desfazer um commit já enviado |
O --hard é o único perigoso: ele descarta o commit e as mudanças. Antes de qualquer reset --hard, guarde o que você tem num stash ou numa branch:
git branch backup-before-reset # seguro barato
git reset --hard HEAD~1 # commit + mudanças apagados Se você já rodou a versão perigosa, nem tudo está perdido — o git reflog lembra por onde o HEAD passou:
git reflog # ache o hash do commit que você perdeu
git reset --hard HEAD@{1} # ou: git reset --hard <hash> O reflog guarda commits órfãos por cerca de 90 dias por padrão, então “dei hard-reset sem querer” é quase sempre recuperável se você agir antes do garbage collection.
E se eu já tiver enviado o commit?
Se o commit está numa branch compartilhada (qualquer uma que não seja a sua feature branch), não reescreva o histórico. Use git revert, que calcula a mudança oposta e a commita:
git revert HEAD
git push Todo mundo que puxar simplesmente recebe um commit novo que remove as mudanças do antigo. Sem force-push, sem colegas quebrados. Para desfazer uma sequência de commits, reverta um intervalo: git revert --no-commit HEAD~3..HEAD && git commit.
A alternativa — git reset --hard HEAD~1 && git push --force-with-lease — só é aceitável numa branch em que ninguém mais constrói, e o --force-with-lease (nunca o --force puro) é a única forma segura, porque recusa a operação se alguém fez push nesse meio-tempo. Force-push em branch compartilhada é assim que times perdem commits e os logs de CI misteriosamente param de bater com o checkout de qualquer um.
Como desfazer o commit mas guardá-lo para depois?
Às vezes o commit é um bom trabalho no endereço errado — na branch errada, ou cedo demais. Em vez de desfazer, mova:
git branch stash-commit # estacione o commit numa branch nova
git reset --hard HEAD~1 # depois limpe a branch atual Ou leve só o commit para outra branch sem tocar na atual:
git cherry-pick <hash> # estando na branch de destino Entre reset --soft, cherry-pick e revert, não existe commit que você não consiga realocar ou anular — o truque é escolher “mover” ou “desfazer” antes de correr para uma flag.
Qual undo usar? Um guia rápido de decisão
- Não enviado, quer corrigir e commitar de novo →
git reset --soft HEAD~1 - Não enviado, quer remontar o stage seletivamente →
git reset HEAD~1(mixed) - Quer as mudanças fora completamente →
git reset --hard HEAD~1(o reflog sabe, se você se arrepender) - Já enviado para uma branch compartilhada →
git revert HEAD - O commit pertence a outra branch →
cherry-pick, não desfaça
Uma última dica operacional: se um commit ruim chegou a um servidor — um hook de deploy que falhou, um runner de CI se comportando mal depois de um force-push — o próximo lugar para olhar são os logs da máquina, não o Git. Em qualquer box com systemd, journalctl -u <service> -n 100 mostra exatamente o que rodou e quando; nosso cheat sheet de journalctl tem os padrões prontos para colar. E se o seu fluxo inclui LLM local para revisar diffs, comparamos as duas opções principais em Ollama vs LM Studio.
— mrsaynothing
Get the next one by email
One email per post. No spam, no algorithms.
what is this?journalctl: cheat sheet para ver e filtrar logs do Linux
Gostou dos artigos? É assim que eu construo profissionalmente. me contrate