Autor: Thiago Marques
Data 21/02/2025
O pai tá on!
Hoje vamos falar sobre um dos superpoderes do Git: voltar no tempo! Sim, igual ao Marty McFly com o DeLorean DMC-12 em De Volta para o Futuro.

Por que desfazer alterações no Git?
-
Bug
Você está desenvolvendo uma feature em uma branch separada, fez um commit de uma nova versão e, durante os testes, descobriu um bug. O ideal é reverter esse commit (com git revert), corrigir o erro e só então fazer o merge com a main. - ‘Mãozada’
Sabe quando você dá um git add . sem pensar e manda arquivos que não devia? Com git restore, dá para remover esses arquivos antes de confirmá-los no commit. - ‘Supermãozada’
Se enviar arquivos errados para uma branch já é ruim, imagina mandar commits errados para a main? Isso é uma supermãozada, mas dá para corrigir com git reset.
Resolvendo o bug com git revert
O git revert cria um novo commit que desfaz as alterações do commit anterior, mantendo o histórico intacto. Assim, você corrige o erro sem bagunçar o repositório.
Resolvendo a ‘mãozada’ com git restore
O restore basicamente remove as alterações da staging area ou até descarta as alterações do working directory, e o mais importante: ele não atualiza a branch, ou seja, não há modificação no histórico.
No exemplo, criamos o arquivo base (base.html) em um commit, depois adicionamos três arquivos (base.html, estilo.css e jinja2.html), cada um em seu próprio commit. Por fim, criamos cursos.html e certificacoes.html, nos quais executamos git add . para colocar todos na staging area.

Depois que fizemos isso, notamos que as novas páginas (hash 6d7204f) foram enviadas erroneamente (a famosa “mãozada”) e, por isso, precisamos removê-las. Para isso, vamos utilizar o seguinte comando:
git restore –source <hash_do_commit_que_quer_voltar> <arquivo>
Nesse caso:
git restore –source 21b9415 .

Note que o histórico de commits não mudou (ainda aparece “novas páginas”). No entanto, os arquivos foram deletados do working directory, como pode ser visto no git status.
Observação: isso também poderia ser feito com o git checkout, e, de fato, o comportamento é o mesmo, com a diferença da flag –source. A questão aqui é mais uma boa prática de arquitetura de software, onde utilizamos comandos específicos para execuções específicas.
Resolvendo a “Supermãozada” com git reset
Com git reset, temos três opções que podem ser utilizadas como parâmetros com –:
- soft: mantém os arquivos do commit na staging area;
- mixed: mantém os arquivos do commit no working directory (opção padrão);
- hard: remove os arquivos do novo commit.
Por exemplo, imagine que você realizou as seguintes ações:
- Commit 1 – hash 1e8f556 – arquivos 1.py, 2.py, 3.py
- Commit 2 – hash 556eabc – arquivos 4.py, 5.py, 6.py
Agora, vamos testar os três tipos de reset, alterando com os seguintes comandos:
git reset –soft 1e8f556
git reset –mixed 1e8f556
git reset –hard 1e8f556
- soft: mantém todos os arquivos, mas 4.py, 5.py e 6.py permanecerão na staging area. Ou seja, será necessário apenas executar git commit -m “” para adicioná-los novamente ao repositório.
- mixed: mantém todos os arquivos, mas 4.py, 5.py e 6.py estarão no working directory (não staged). Isso significa que será preciso executar git add . seguido de git commit -m “” para adicioná-los ao repositório.
- hard: apaga os arquivos do commit 2 (556eabc), como se eles nunca tivessem existido.
Observação: Para visualizar essas alterações, você pode validar os logs de referência com o comando:
git reflog
That’s all folks! Be Happy!!!

thiago.marques@darede.com.br
Technical Account Manager da Darede, formato em Rede de Computadores, e pós graduado em Segurança da Informação. Possui ampla experiência em Datacenters e Service Providers, além de ser um entusiasta em DevOps e mercado financeiro.