Voltar ao blog

Git revert vs reset: qual salva o seu histórico?

15 de setembro de 2026

TL;DR: o git revert cria um novo commit que desfaz um antigo — o histórico é preservado, seguro em branches que outras pessoas já puxaram. O git reset move o ponteiro da branch para trás — o histórico é reescrito, só seguro em commits que você ainda não fez push. Use revert em branches compartilhadas, reset em limpeza local. O reset --hard também apaga mudanças não commitadas do working tree; é ele que come trabalho de verdade.

Qual a diferença entre git revert e git reset?

Os dois fazem seu projeto parecer que um commit do passado nunca aconteceu. Eles discordam sobre como:

  • git revert <sha> calcula o patch inverso de um commit e o commita. Seu histórico cresce um commit que diz “desfaça aquele”. O commit ruim continua no log, seguido do seu cancelamento. Os SHAs de todo o resto ficam intactos.
  • git reset <sha> move o ponteiro da branch atual para <sha>. Os commits depois dele ficam soltos — ainda na base de objetos até a garbage collection, mas inalcançáveis por qualquer branch ou git log.

Uma não reescreve nada; a outra finge que nada aconteceu. Essa única propriedade decide qual cada situação pede:

# Demo: um repositório descartável e executável
git init /tmp/revert-vs-reset && cd /tmp/revert-vs-reset
echo one > file.txt && git add . && git commit -m "one"
echo two > file.txt && git add . && git commit -m "two"

# Revert: o histórico mantém os dois commits, mais um terceiro que desfaz o "two"
git revert --no-edit HEAD
git log --oneline        # 3 commits: revert, two, one

# Reset: o ponteiro da branch volta, e o "two" some do log
git reset --hard HEAD~1
git log --oneline        # 1 commit: one

Rode os dois e olhe o git log — a assimetria é a resposta inteira.

O que git reset —soft, —mixed e —hard fazem de fato?

Os três modos controlam onde suas mudanças sobrevivem depois que o ponteiro anda:

ModoPonteiro da branchStaging areaWorking treeSuas edições
--softvoltamantém stagedintocadomantidas por inteiro
--mixed (padrão)voltaunstagedintocadomantidas, unstaged
--hardvoltaresetadaresetadaapagadas

Leituras concretas dessa tabela:

  • git reset --soft HEAD~1 — “comitei cedo demais.” Tudo volta para staged, pronto para recommittar, talvez junto com mais trabalho.
  • git reset HEAD~1 (mixed) — “staged os arquivos errados.” As edições sobrevivem no working tree, nada fica staged. Combine com remover arquivos untracked do git quando também quiser os arquivos perdidos fora.
  • git reset --hard HEAD~1 — “esse commit e minhas edições não commitadas são lixo.” O git não pergunta duas vezes; não há undo para a parte do working tree a menos que você tenha stashado ou commitado antes.

O revert não tem modos porque nunca destrói nada — ele só adiciona um commit compensatório.

Quando usar git revert em vez de git reset?

Faça uma pergunta: outra pessoa já puxou esse commit? Se sim, reset está fora de questão.

Resetar uma branch na qual outros basearam trabalho reescreve o histórico compartilhado. O próximo pull deles encontra branches divergentes, e o “conserto” costuma ser um force-push que transforma o seu erro em problema de todo mundo. O revert anexa um commit normal, então um git pull simples faz merge limpo para todos — por isso revert é a resposta padrão na main e nos pull requests do GitHub, onde o botão “Revert” existe justamente porque reescrever o histórico de um PR mergeado não é opção.

O reset é para a janela antes de compartilhar: o commit feito trinta segundos atrás, o erro de staging, a branch de experimento local. Se a única cópia do trabalho está na sua máquina, você pode rearranjar o histórico à vontade — esse é todo o propósito da janela pré-push.

Há um caso intermediário: você fez push para a sua própria feature branch e ninguém mais constrói sobre ela. Um force-push depois do reset é socialmente aceitável ali, mas o revert ainda custa menos coordenação. Reserve force-pushes para branches que são suas e de mais ninguém.

O git revert é mais seguro que o git reset em branches compartilhadas?

Sim, estruturalmente — não só por convenção:

  • O revert produz um commit comum; o CI roda nele, o diff é revisável, e o git log explica para o você-do-futuro por que a mudança sumiu.
  • O reset descarta o estado intermediário em silêncio. Ninguém revisando depois consegue ver o que foi desfeito ou quando, porque o log mostra uma linha reta que nunca o contém.

Duas arestas práticas:

  • Reverter um merge commit pede git revert -m 1 <sha> (manter a linha do primeiro pai). Sem o -m, o git recusa e te deixa lendo o erro.
  • Revert não é máquina do tempo: ele desfaz o diff de um commit. Se commits posteriores mexeram nas mesmas linhas, você pode resolver conflitos — é o git te dizendo que o undo está enroscado, o que é informação útil, não defeito.

Para desfazer especificamente o seu último commit — mantendo ou descartando as mudanças — as opções estão em git undo last commit: mantenha as mudanças.

E o git restore, onde ele entra?

O git restore (e o git switch, seu par) chegaram no git 2.23 para assumir os trabalhos que o reset fazia mal por sobrecarga de nome:

TarefaJeito antigoJeito claro
Descartar edições do working tree em um arquivogit checkout -- file / git reset --hardgit restore file
Tirar um arquivo da staging areagit reset HEAD filegit restore --staged file
Mover uma branch para outro commitgit reset <sha>git reset <sha> (sem substituto — esse fica)

Então a divisão moderna é: restore conserta arquivos, reset move branches, revert desfaz commits publicados. O autocomplete mostra que as pessoas pesquisam “git revert vs reset vs restore” juntas com razão — são um modelo mental dividido em três comandos. As formas antigas do git checkout funcionam em todo lugar; as novas apenas te impedem de mandar uma branch inteira para o triturador quando você só queria unstagar um arquivo.

Se o objetivo é copiar um commit bom para frente em vez de apagar um ruim, esse é o trabalho do cherry-pick — veja git cherry-pick: múltiplos commits, branches e conflitos.

Recap rápido de decisão

  1. Commit público (push feito, outras pessoas já puxaram) → git revert <sha>.
  2. Commit só local, quer refazê-lo → git reset --soft ou --mixed e commitar de novo.
  3. Só local, quer fora junto com a bagunça não commitada → git reset --hard, depois de uma olhada honesta no que mais o working tree guarda.
  4. Um arquivo foi estragado → git restore <file> e deixe a branch em paz.

A única entrada genuinamente perigosa da lista é o --hard — todo o resto se recupera conversando com o git reflog. As perdas permanentes no git são estreitas e quase sempre exigem que você digite o comando explicitamente; o hábito que vale construir é pausar meio segundo antes do --hard, não evitar as ferramentas afiadas do git.

— mrsaynothing

Get the next one by email

One email per post. No spam, no algorithms.

self-hosted · no third parties · one-click unsubscribe

what is this?

Serviço systemd não inicia? Como resolver

Gostou dos artigos? É assim que eu construo profissionalmente. me contrate