Podemos comprometer uma aplicação mesclando código problemático, seja por integrar acidentalmente trabalho inacabado no branch principal ou por passar despercebido um bug crítico que escapou aos testes automatizados.
Neste artigo, vou guiá-lo pelo processo de usar git revert
para desfazer uma mesclagem de forma segura, garantindo que o histórico de commits permaneça intacto e a integridade do projeto seja preservada.
Como git revert
Funciona
Podemos pensar no git revert
como o comando de desfeito do Git. No entanto, o comando git revert
não exclui commits ou salta para um estado anterior do branch. Em vez disso, ele cria um novo commit que reverte as mudanças de um commit específico.
A sintaxe para reverter um commit com o hash <commit_hash>
é:
git revert <commit_hash>
Podemos listar os commits juntamente com seus identificadores de hash usando o comando git log
. A saída do git log
lista os commits do mais recente para o mais antigo, como assim:
Por exemplo, para reverter o commit que implementa a função de subtração, usaríamos o comando:
git revert 7ba24a3e62d4d37182428ccfaa070baa222b1151
Usando git revert
podemos desfazer as mudanças de um commit específico sem afetar o histórico de commits.
Note que o git revert
não é mágico e, dependendo do histórico de commits, pode resultar em um conflito que precisa ser resolvido manualmente.
Vantagens do git revert
Sobre Mudanças Manuais
Por que o git revert
é útil se podemos precisar resolver um conflito manualmente? Não seria mais fácil desfazer as mudanças manualmente? Vamos ver suas vantagens:
- Preserva o histórico: o
git revert
cria um novo commit que desfaaz as mudanças de um commit específico, preservando todo o histórico de commits. Isso ajuda a manter um histórico transparente de mudanças e reversões. - Reversão atômica: garante que as reversões são atômicas e consistentes. Quando deletamos e commitamos mudanças manualmente, há um risco de erro humano.
- Consciência de conflitos: garante que somos alertados por meio de conflitos se há alguma integração ou mudanças dependentes do commit original. Isso pode parecer inconveniente, mas evita efeitos colaterais indesejados.
- Metadados: o novo commit criado pelo git revert inclui metadados e uma mensagem de commit que descreve contextualmente o que foi revertido, auxiliando em uma futura compreensão. Sem o
git revert
, esse contexto pode ser perdido.
Reverter uma Fusão em Diferentes cenários
Nesta seção, aprendemos como desfazer uma fusão. Para fins de exemplo, estamos supondo que estamos mesclando um分支 chamado feature
no branch main
executando o comando a partir do branch main
:
git merge feature
O que aprendemos aqui pode ser aplicado a qualquer dois branches substituindo os nomes apropriadamente.
Revertendo uma mesclagem que não tem commit associado
O comando git merge
nem sempre cria um novo commit. Um commit é criado apenas se o branch main
divergir do branch feature
. Como o git revert
requer um commit para operar, não podemos usá-lo neste caso.
Os branches main
e feature
divergem quando novos commits são criados no main
que não são ancestrais do branch feature
. Em outras palavras, novos commits foram criados no main
após a criação do feature
.
Se os branches não divergiram, ao executarmos o comando git merge feature
no branch main, o Git usará o fast-forward para mesclar. Isso significa que ele move o HEAD
do branch main
para o HEAD
do branch feature
.
Podemos observar que isso aconteceu olhando para o resultado do git merge
:
Para desfazer essa mesclagem, precisamos apenas mover o HEAD
do branch main
de volta para onde ele estava. Para isso, nós:
- Identificamos o
HEAD
anterior usando ogit reflog
- Reinicia o
HEAD
para o anterior usandogit reset --hard <previous_head>
, substituindo<previous_head>
peloHEAD
anterior.
A saída do git reflog
terá um aspecto parecido com este:
Podemos identificar o HEAD
anterior olhando para a linha que diz “checkout: moving from feature to main” (ela escreve feature
e main
porque esses são os nomes dos nossos branches).
Neste caso, o HEAD
anterior é fe59838
. Para mover o HEAD
do branch principal de volta para ele e desfazer a mesclagem, usamos o comando:
git reset --hard fe59838
Revertendo uma mesclagem que tem um commit associado
Se o branch main
e o branch feature
divergiram, então quando mesclamos dois branches, um novo commit é criado, chamado commit de mesclagem.
O commit de mesclagem aplica as mudanças de um branch para o outro. Neste caso, as mudanças no feature
são aplicadas ao branch main
.
Para reverter as mudanças no branch main
, usamos o git revert
no commit de mesclagem. Isso criará um novo commit que desfaz as mudanças trazidas para o branch main
pela mesclagem, restaurando efetivamente o estado do branch principal ao que era antes da mesclagem.
Primeiro, precisamos identificar o hash do commit de mesclagem. Podemos fazer isso usando o comando git log
:
Como o commit de mesclagem tem dois pais, a sintaxe do git revert
é ligeiramente diferente. Precisamos usar a opção -m 1
para especificar que queremos reverter as mudanças em relação ao branch main
:
git revert -m 1 b8dab2c8611e324ed0d273133987415350e6d10d
Resolução de Conflitos ao Reverter um Commit
Algumas vezes, podem surgir conflitos ao reverter um commit, especialmente se o commit a ser revertido entra em conflito com mudanças posteriores no código base. Nestes casos:
- Git pausará a reversão: Precisamos resolver manualmente os conflitos. Git marcará os arquivos em conflito e exigirá intervenção.
- Resolver os conflitos: Abrimos cada arquivo em conflito, resolvemos os conflitos marcados pelo Git e salvamos as mudanças.
- Adicionar os arquivos resolvidos ao índice:
git add <caminho-do-arquivo>
- Continuar a reversão:
git revert --continue
Conclusão
Usar git revert
para desfazer commits de mesclagem garante que todas as mudanças e correções sejam documentadas dentro do histórico de commits.
Além disso, entender os cenários apropriados para aplicar git reset
versus git revert
nos permite tomar melhores decisões, especialmente ao considerar fluxos de trabalho colaborativos ou mudanças apenas locais.
Você pode ler mais sobre esse assunto na seção de FAQ abaixo. Se você quiser aprender mais sobre Git, recomendo esses recursos: