Voltar atrás no Git: restore, reset e revert
Três comandos para desfazer coisas, e a confusão entre eles é responsável por boa parte do trabalho perdido em Git. A diferença resume-se a o que é que cada um mexe.
1. Deitar fora alterações que ainda não foram comitadas
# Um ficheiro, como está no último commit
git restore src/servidor.ts
# Tirar do staging, mas manter as alterações
git restore --staged src/servidor.tsO git restore apareceu para separar isto do git checkout, que fazia tudo e era ambíguo. Atenção: o que ele deita fora não está em lado nenhum. Não há reflog que salve trabalho que nunca chegou a ser comitado.
2. Mexer no ponteiro do ramo: reset
# Desfaz o commit, guarda tudo em staging (para refazer a mensagem)
git reset --soft HEAD~1
# Desfaz o commit e o staging; os ficheiros ficam alterados
git reset HEAD~1
# Desfaz tudo. As alterações desaparecem.
git reset --hard HEAD~1O reset reescreve a história do ramo. É seguro no que ainda é só seu; num ramo partilhado, obriga toda a gente a um force push e à confusão que vem a seguir.
3. Desfazer em público: revert
git revert a3f9c21Não apaga nada: cria um commit novo que faz o contrário do antigo. A história fica mais comprida e fica honesta — mostra que houve um erro e que foi corrigido. É a única opção defensável para desfazer o que já foi publicado.
4. A rede de segurança que quase ninguém conhece
git reflogO reflog guarda todos os sítios onde o HEAD esteve nos últimos 90 dias — incluindo os que um reset --hard "apagou". Um commit que parece perdido está quase sempre ali:
git reflog
# a3f9c21 HEAD@{0}: reset: moving to HEAD~1
# 7b2e441 HEAD@{1}: commit: a funcionalidade que eu tinha acabado
git reset --hard 7b2e441Antes de entrar em pânico com trabalho perdido em Git, é sempre o primeiro sítio a olhar.