Introdução
Aprenda a desfazer alterações e commits no Git com checkout, restore, reset, revert, clean e amend — com exemplos claros e quando usar cada comando.

Ao contrário da maioria dos editores, o Git não possui um único botão de "desfazer". Em vez disso, ele oferece um pequeno conjunto de comandos, cada um visando uma área diferente onde o seu trabalho reside: o diretório de trabalho (os arquivos em disco), o índice de staging (alterações marcadas para o próximo commit) e o histórico de commits (snapshots já registrados). Escolher o comando certo depende de qual dessas três áreas você quer reverter e se a alteração foi compartilhada com outras pessoas.
Esta página cobre o conjunto completo de ferramentas: revisar o histórico, restaurar arquivos e desfazer um ou vários commits — com git checkout, git restore, git reset, git revert, git clean e git commit --amend.
Escolhendo o comando certo
Antes de qualquer comando específico, é útil saber qual área cada um afeta e se ele reescreve o histórico:
| Objetivo | Comando | Seguro para compartilhar? |
|---|---|---|
| Descartar edições em um arquivo rastreado | git restore <file> (ou git checkout -- <file>) | sim |
| Remover um arquivo do staging | git restore --staged <file> (ou git reset HEAD <file>) | sim |
| Excluir arquivos não rastreados | git clean | sim |
| Corrigir o commit mais recente | git commit --amend | somente se não foi enviado |
| Mover o branch de volta a um commit anterior | git reset | somente local |
| Cancelar um commit adicionando um inverso | git revert | sim |
A regra mais importante: reset e amend reescrevem o histórico, portanto use-os apenas em commits que você não enviou. Para qualquer coisa já compartilhada, use revert.
Revisando commits antigos
Você não pode desfazer o que não consegue encontrar. A melhor ferramenta para revisar o histórico é o git log. Cada commit possui um hash de identificação que você usa para referenciá-lo:
git log --oneline
a3b2a21 Crossword solver with Vue.js
c54ce02 New logic for crossword game
3acb8d0 Some changes in crossword logic
de32112 Styling crossword table areaPor padrão, git log exibe apenas os commits acessíveis a partir do branch atual. Para visualizar commits em todos os branches, adicione --all. Use git checkout ou git switch para visitar outros branches.
Visualizando uma revisão antiga
Para inspecionar o projeto como ele era em um ponto anterior, primeiro encontre o hash da revisão desejada:
git log --oneline
b7119f2 Changes in Scrabble Solver
234be24 Fixing search input bug
b235bf4 Make some changes to solver.php
256a81c Create solver.php
3243e12 Initial changesEm seguida, faça o checkout desse commit pelo seu hash:
git checkout b235bf4Agora você pode navegar pelos arquivos, executar testes e até editar coisas. Nada do que você fizer aqui é registrado em um branch, portanto seu trabalho atual está seguro. Esse estado temporário é chamado de HEAD desanexado — o HEAD aponta diretamente para um commit em vez de para a ponta de um branch. Volte para o seu branch quando terminar:
git switch - # or: git checkout masterUma vez de volta ao seu branch, use git revert ou git reset para desfazer qualquer alteração desejada.
Desfazendo um snapshot commitado
Há várias formas de desfazer um commit. A escolha certa depende se o commit foi compartilhado. Imagine que nosso histórico se parece com este:
git log --oneline
863fa8e Making some improvements
b235bf4 Make some changes to solver.php
256a81c Create solver.php
3243e12 Initial changesAs seções abaixo desfazem o commit 863fa8e Making some improvements de três maneiras diferentes.
Com git checkout (inspecionar sem alterar o branch)
Fazer o checkout do commit anterior, b235bf4, coloca o repositório no estado anterior ao commit de melhorias:
git checkout b235bf4Esse é um desvio quase somente leitura, não um desfazimento real: você acaba em um estado de HEAD desanexado. Qualquer novo commit que você fizer aqui se tornará órfão assim que você voltar para um branch estabelecido, e o coletor de lixo do Git poderá eventualmente removê-lo. Para manter o trabalho feito a partir deste estado, crie um branch a partir dele:
git checkout -b improvements-removedAgora você tem um novo branch, improvements-removed, cujo histórico nunca incluiu 863fa8e. O checkout é melhor para visualizar um estado antigo; os próximos dois comandos realmente desfazem o commit.
Com git revert (o desfazimento seguro e compartilhável)
git revert HEAD cria um novo commit que aplica o inverso do commit alvo. Nada é apagado — o histórico avança:
git revert HEADApós executá-lo, o log fica assim:
git log --oneline
23a4b42 Revert "Making some improvements"
863fa8e Making some improvements
b235bf4 Make some changes to solver.php
256a81c Create solver.php
3243e12 Initial changesO efeito de 863fa8e agora está cancelado, mas o commit ainda está no histórico; 23a4b42 simplesmente reverte suas alterações. Como nada é reescrito, você permanece no mesmo branch e nunca prejudica o clone de ninguém. Este é o desfazimento correto para commits que foram enviados ou compartilhados publicamente.
Com git reset (reescrever o histórico local)
git reset move o ponteiro do branch atual para um commit escolhido. Executar git reset --hard b235bf4 retrocede o branch para esse commit e descarta tudo o que vem depois:
git reset --hard b235bf4
git log --oneline
b235bf4 Make some changes to solver.php
256a81c Create solver.php
3243e12 Initial changesO commit 863fa8e foi removido do histórico deste branch. Isso é limpo e direto, mas como reescreve o histórico, você só deve fazê-lo em commits que ainda não foram enviados. git reset aceita um sinalizador de modo que controla até onde o desfazimento alcança:
--soft— move apenas o ponteiro do branch; mantém as alterações em staging.--mixed(padrão) — move o ponteiro e retira as alterações do staging, mas as mantém no diretório de trabalho.--hard— move o ponteiro e descarta as alterações em staging e no diretório de trabalho.
git reset --hard descarta permanentemente o trabalho não commitado no diretório de trabalho. Não há etapa de staging para recuperá-lo. Use --soft ou --mixed quando quiser apenas refazer o commit, mas manter as edições.
Desfazendo o último commit
Às vezes você não quer remover o commit mais recente — você apenas commitou cedo demais ou escreveu uma mensagem ruim. Adicione ao staging quaisquer alterações extras com git add e, em seguida, faça o amend:
git add forgotten-file.txt
git commit --amendO Git abre o editor configurado para que você possa editar a mensagem do último commit, e as alterações recém-adicionadas ao staging são incorporadas a esse mesmo commit. Para alterar apenas a mensagem em uma linha:
git commit --amend -m "A clearer message"O amend substitui o commit anterior por um novo (com um novo hash), portanto, trate-o como reset: só faça o amend em commits que você não enviou.
Desfazendo alterações não commitadas
Antes de um commit, uma alteração vive no diretório de trabalho e no índice de staging, portanto você pode desfazê-la em qualquer uma dessas áreas sem tocar no histórico. O comando moderno é git restore:
# Discard edits to a tracked file (working directory)
git restore <file>
# Unstage a file but keep its edits
git restore --staged <file>Os equivalentes mais antigos ainda funcionam e aparecem em muitas documentações:
# Discard changes in the working directory
git checkout -- <file>
# Unstage a file
git reset HEAD <file>Removendo arquivos não rastreados
git restore e reset afetam apenas arquivos que o Git já conhece. Para excluir arquivos novos e não rastreados, use git clean. Sempre faça uma prévia primeiro com -n (execução simulada):
git clean -n # list what would be removed
git clean -f # actually remove untracked filesComo as três áreas se relacionam
Vale a pena manter as três áreas claras, pois cada comando de desfazimento tem como alvo uma delas específica:
- Diretório de trabalho — os arquivos em disco que o seu editor modifica.
git restore <file>egit cleanoperam aqui. - Índice de staging — o snapshot que você está construindo para o próximo commit.
git addcoloca as alterações aqui;git restore --staged(um reset--mixed) as empurra de volta para o diretório de trabalho. - Histórico de commits — snapshots registrados.
git reseto reescreve;git revertadiciona a ele.
Recuperando-se de um desfazimento equivocado
Um reset ou um branch excluído pode parecer aterrorizante, mas o Git raramente perde algo imediatamente. O git reflog registra onde o HEAD apontou, então você pode encontrar o hash de um commit "perdido" e fazer o reset de volta para ele:
git reflog
1a2b3c4 HEAD@{0}: reset: moving to b235bf4
863fa8e HEAD@{1}: commit: Making some improvementsRecupere com git reset --hard 863fa8e (ou crie um branch a partir dele). Se você quiser apenas guardar o trabalho temporariamente em vez de desfazê-lo, considere usar o git stash.
Desfazendo alterações públicas
Assim que um commit é enviado, outras pessoas podem tê-lo. Use git revert para alterações públicas, nunca git reset. O reset remove commits do histórico, então reescrever um branch compartilhado força todos os outros a reparar seus clones. O revert deixa o commit original no lugar e registra um novo commit que o reverte — seguro para todos que já fizeram o pull.