Como reverter um commit no git

Existem algumas maneiras diferentes de desfazer as coisas no git, mas para o propósito deste post vamos considerar o seguinte cenário:

  • um repositório com cópias locais e remotas
  • vários colaboradores
  • um commit recente que já foi adicionado ao repositório remoto (“merged”, pra usar o termo “git” em inglês) mas que precisa ser revertido

git revert pra resolver esse problema! ✨

RESUMÃO: passos pra reverter um commit em um repositório remoto:

  • atualize a cópia local do repostitório na seu branch principal: git pull
  • crie um novo branch: git checkout -b remove_codigo_bugado
  • encontre o hash do commit com bugs com git log
  • git revert <hash_do_commit_que_vai_ser_desfeito> [-m 1 –no-edit]

O comando acima criará um novo commit onde todas as alterações do commit original que foi adicionado ao repositório remoto serão revertidas. Isso é bom porque fazendo desse jeito você mantém o histórico do repositório inalterado.

As opções opcionais mostradas no comando acima significam:

-m n : se você está revertendo um “merge” commit (o commit final que foi adicionado ao repositório remoto), você precisa passar esta opção com um número ( tem uma entrada em inglês no StackOverflow explicando o porquê )

–no-edit : (note que são dois traços no início da opção!) isso vai evitar que o editor de texto padrão abra automaticamente

EXEMPLO passo-a-passo:

Meu branch principal e local chamado main tá assim:

└❯ git log
commit 9ebef49af9f50996f32c863604b1fc6fdce71e26 (HEAD -> main, origin/main, origin/HEAD)
Author: Flavia Bastos <meu_email>
Date:   Tue Oct 4 19:22:55 2022 -0300

    Corrigir ortografia

Nesse meio tempo alguém adiciona um commit novo no repositório remoto. Quando eu puxo as alterações novas pro meu repositório local, eu vejo o commit novo ( 86d1c24f17aa7) e um merge commit novo ( 5aa51c6ea265cc) para essas alterações:

└❯ git log
commit 5aa51c6ea265cc43b93a66de97ca4d8fcafc69df (HEAD -> main, origin/main, origin/HEAD)
Merge: 9ebef49 86d1c24
Author: Outra pessoa <outro_email>
Date:   Thu Oct 6 17:14:15 2022 -0400

    Merge pull request #1 from Outra pessoa/caso_123
    
    Codigo novo cheio de firula

commit 86d1c24f17aa7fd264a26d81533e53f6f48dea24 (origin/caso_123, caso_123)
Author: Outra pessoa <outro_email>
Date:   Thu Oct 6 18:08:49 2022 -0300

    Codigo novo cheio de firula

commit 9ebef49af9f50996f32c863604b1fc6fdce71e26
Author: Flavia Bastos <meu_email>
Date:   Tue Oct 4 19:22:55 2022 -0300

    Corrigir ortografia

Observe aqui que o merge commit ( 5aa51c6ea265cc) também descreve os commits antecedentes no atributo “Merge”:

Merge: 9ebef49 86d1c24

Daí acontece que esse código sofisticado também estava com bugs e fez com que algumas coisas quebrassem feio. Quem nunca, neah? 👀

Vamos corrigir isso rapidamente criando um branch novo a partir da última atualização da branch principal (main):

└❯ git checkout -b corrige_bug
Switched to a new branch 'corrige_bug'

A partir da mensagem do comando git log acima, sabemos que queremos o hash do commit mais recente (o primeiro da lista nesse caso), mas pode haver outros commits novos depois dele. Sempre confirme rodando o git log de novo.

Agora vamos reverter o commit com bug ( 5aa51c6ea265cc) – observe que estamos em um branch separado e estou usando a opção -m 1 , porque quero reverter para seu primeiro antecedente 9ebef49 (se eu usasse -m 2 ao invés, ele reverteria para o segundo antecedente 86d1c24):

└❯ git revert 5aa51c6ea265cc43b93a66de97ca4d8fcafc69df -m 1 --no-edit
[corrige_bug 560ad2d] Revert "Merge pull request #1 from Outra pessoa/caso_123"
 Date: Thu Oct 6 18:30:50 2022 -0300
 1 file changed, 1 insertion(+), 1 deletion(-)

O úlimo passo agora é mandar esse branch  corrige_bug pro repositório remoto e dar merge na alteração:

└❯ git push origin corrige_bug
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 402 bytes | 402.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
remote: 
remote: Create a pull request for 'corrige_bug' on GitHub by visiting:
remote:      https://github.com/FlaviaBastos/meu_projeto/pull/new/corrige_bug
remote: 
To github.com:FlaviaBastos/meu_projeto.git
 * [new branch]      corrige_bug -> corrige_bug

Depois que essa última alteração for adicionada ao repositório remoto, volte para o branch principal main no seu repositório local, puxe as últimas alterações e confirme com o git log que o commit com erros foi revertido:

❯ git log
commit 4332e3e999c2056019cf64255f17b32a6ef1992b (HEAD -> main, origin/main, origin/HEAD)
Merge: 5aa51c6 560ad2d
Author: Outra pessoa <outro_email>
Date:   Thu Oct 6 17:53:28 2022 -0400

    Merge pull request #2 from FlaviaBastos/corrige_bug
    
    Revert "Merge pull request #1 from Outra pessoa/caso_123"

commit 560ad2ddfd207fad2f609873270bdd3f645bb4b6 (origin/corrige_bug, corrige_bug)
Author: Flavia Bastos <my_email>
Date:   Thu Oct 6 18:30:50 2022 -0300

    Revert "Merge pull request #1 from Outra pessoa/caso_123"
    
    This reverts commit 5aa51c6ea265cc43b93a66de97ca4d8fcafc69df, reversing
    changes made to 9ebef49af9f50996f32c863604b1fc6fdce71e26.

commit 5aa51c6ea265cc43b93a66de97ca4d8fcafc69df (HEAD -> main, origin/main, origin/HEAD)
Merge: 9ebef49 86d1c24
Author: Outra pessoa <outro_email>
Date:   Thu Oct 6 17:14:15 2022 -0400

    Merge pull request #1 from Outra pessoa/caso_123
    
    Codigo novo cheio de firula

Ufa! Tudo resolvido! 😅

MAS peraí, o RESET --HARD faz a mesma coisa, não?

Sim. Porém, apenas localmente. O comando git reset vai mover o ponteiro do seu repositório para qualquer commit que você definir, efetivamente removendo qualquer coisa depois dele. Se você rodar um git status, você não verá mais esses outros commits, nem nada de novo que precise ser feito commit e você estará reescrevendo o histórico do repositório desse jeito. Isso só é seguro se você estiver trabalhando sozinho ou em um branch que ainda não foi mandado e anexado ao repositório remoto.

Se você precisar enviar as alterações de reversão de commit para um repositório remoto, você deve usar o git revert.

Pra saber mais:

Documentação do git revert: https://git-scm.com/docs/git-revert/pt_BR


Compartilhe esse artigo!

Como reverter um commit no git

O artigo Como reverter um commit no git foi publicado originalmente no flaviabastos.ca