Desfazendo Alterações no Git: Reset, Restore, Revert Explicados

Entenda git restore, reset e revert para que você possa desfazer arquivos do stage, descartar edições locais, desfazer commits e evitar reescrever histórico compartilhado.

Desfazendo Alterações no Git: Reset, Restore, Revert Explicados

Desfazer alterações no Git é seguro quando você sabe qual camada está alterando: a árvore de trabalho, a área de staging ou o histórico de commits. Os comandos comuns são git restore, git reset e git revert, e eles resolvem problemas diferentes.

A grande regra é simples: use restore para arquivos, reset para alterações no histórico local e revert para desfazer commits que outras pessoas já podem ter.

Entendendo os Conceitos Principais

Mantenha essas áreas claras:

  • Árvore de trabalho: os arquivos que você edita.
  • Área de staging, também chamada de índice: as alterações selecionadas para o próximo commit.
  • Histórico de commits: os commits já registrados.
  • HEAD: o commit atual para o qual seu branch aponta.

Execute git status antes de desfazer qualquer coisa. Ele informa se as alterações estão não preparadas (unstaged), preparadas (staged) ou já commitadas.

git restore: Para Descartar Alterações no Diretório de Trabalho e na Área de Staging

Use git restore quando quiser alterar arquivos na árvore de trabalho ou na área de staging sem mover o histórico do branch.

Desfazendo Arquivos do Stage

Se você preparou um arquivo por engano, remova-o do stage com --staged:

git restore --staged <arquivo>

Para remover tudo do stage:

git restore --staged .

Suas edições no arquivo permanecem na árvore de trabalho. Elas são simplesmente removidas do próximo commit.

Descartando Alterações no Diretório de Trabalho

Para descartar edições não preparadas em um arquivo:

git restore <arquivo>

Isso faz a cópia da árvore de trabalho corresponder ao índice. Se o arquivo não estiver preparado, isso geralmente significa que ele volta para HEAD. Revise git diff primeiro, pois isso descarta edições locais.

Para descartar alterações preparadas e não preparadas de um arquivo e restaurá-lo de HEAD:

git restore --source=HEAD --staged --worktree <arquivo>

Restaurando um Arquivo de um Commit Específico

Você também pode trazer de volta um arquivo de um commit mais antigo:

git restore --source=<commit> -- caminho/para/arquivo

Isso altera o arquivo em sua árvore de trabalho. Faça commit se a versão antiga for o que você deseja daqui para frente.

git reset: Reescrevendo o Histórico

Use git reset quando quiser mover o ponteiro do branch atual. Ele também pode alterar a área de staging e a árvore de trabalho, dependendo do modo.

Entendendo os Modos (--soft, --mixed, --hard)

Os três modos comuns são:

git reset --soft HEAD^

Move HEAD um commit para trás e mantém as alterações do commit desfeito preparadas (staged).

git reset --mixed HEAD^

Move HEAD um commit para trás e mantém as alterações do commit desfeito não preparadas (unstaged). --mixed é o padrão, então git reset HEAD^ faz o mesmo.

git reset --hard HEAD^

Move HEAD um commit para trás e descarta as alterações correspondentes da área de staging e da árvore de trabalho. Isso é destrutivo. Não execute casualmente.

Padrões úteis de reset:

git reset --soft HEAD^      # refaça o último commit local, mantenha alterações preparadas
git reset HEAD^             # desfaça o último commit local, mantenha alterações não preparadas
git reset                   # remova todas as alterações preparadas do stage
git reset --hard origin/main # descarte alterações locais e corresponda a origin/main

Resetando um Commit Antigo

Para mover seu branch dois commits para trás enquanto mantém as alterações em sua árvore de trabalho:

git reset --mixed HEAD~2

Apenas redefina commits que são locais ou que sua equipe concordou em reescrever. Se os commits já estão em um branch compartilhado, prefira git revert.

git revert: Criando um Novo Commit para Desfazer Alterações

git revert cria um novo commit que aplica o inverso de um commit anterior. Ele não exclui ou move o commit original, portanto é seguro para branches compartilhados.

Reverter um commit:

git revert <hash-do-commit>

Reverter um intervalo:

git revert HEAD~3..HEAD

Se conflitos aparecerem, resolva-os, prepare os arquivos e continue:

git add <arquivos-corrigidos>
git revert --continue

Reverter um commit de merge requer cuidado extra porque o Git precisa saber qual pai deve ser tratado como a linha principal:

git revert -m 1 <commit-de-merge>

Faça isso apenas quando você entender o que o merge introduziu. Para branches de produção, peça uma revisão antes de reverter merges.

Escolhendo o Comando Correto

Use este guia rápido:

  • Remover um arquivo do stage: git restore --staged <arquivo>.
  • Descartar edições não preparadas em um arquivo: git restore <arquivo>.
  • Desfazer o último commit local e manter alterações preparadas: git reset --soft HEAD^.
  • Desfazer o último commit local e manter alterações não preparadas: git reset HEAD^.
  • Descartar alterações e commits locais destrutivamente: git reset --hard <commit>.
  • Desfazer um commit enviado com segurança: git revert <hash-do-commit>.

Conclusão Prática

Antes de desfazer qualquer coisa, execute git status e decida o que você está alterando. Use restore para limpeza em nível de arquivo, reset para commits locais não enviados e revert para histórico compartilhado. Quando um comando incluir --hard, pause e verifique git diff primeiro.