# Como Reverter Múltiplos Commits no GIT

*Publicado na versão antiga do blog em 22 de dezembro de 2021*

Recorrentemente, o desenvolvedor de software necessita retroceder vários *commits* a fim de voltar seu código para uma versão estável. Um exemplo disso é quando temos um fluxo de trabalho onde um repositório GIT tem suas *branches* associadas à ambientes de implantação através de *pipelines* DevOps, tal como o exemplo da Figura 1, a seguir:

![](https://douglasdantas.com/wp-content/uploads/2021/12/image-1.png align="left")

**Figura 1:** Exemplo de GIT Flow com *pipeline* típico.

Para que uma versão “suba” para homologação, seria necessário que se fizesse um *merge* *request* da *branch* “feature-new-func” em “develop” e, por sua vez, de “develop” em “master”. Enquanto o ambiente de homologação está em uma dada versão, associada a um *commit* específico, é possível que a *branch* “develop” fique bem mais atualizada conforme as atividades de desenvolvimento ocorrem, conforme mostra a Figura 2:

![](https://douglasdantas.com/wp-content/uploads/2021/12/image-2.png align="left")

**Figura 2:** Exemplo de diferenças de histórico entre as *branches* citadas no exemplo anterior.

Como fazer então para que, caso necessitemos ter em “develop” a versão estável do *commit* A novamente, possamos reverter sem quebrar o fluxo e perder o histórico?

Encontrei a solução recentemente, ao passar por esse problema no meu trabalho, no [Stack Overflow](https://stackoverflow.com/questions/1463340/how-to-revert-multiple-git-commits), onde o autor da resposta dá os créditos da abordagem a Jeff Ferland e Charles Bailey. Ela pode ser resumida assim:

```bash
$ git reset --hard A # A é o commit alvo
$ git reset --soft D # D é o commit mais recente
$ git commit -am "Rollback to commit A"
```

Basicamente, o git reset –hard destrói todas as mudanças que aconteceram após o *commit* A, voltando para ele. Em seguida, o git reset –soft “voltará” para o *commit* D, o mais atual, mais as mudanças necessárias para que se chegasse ao *commit* A. O resultado será um novo *commit* idêntico ao *commit* que se quer reverter, preservando-se o histórico. Observe que se você por o código do alvo na mensagem do novo *commit*, o ambiente de GIT poderá criar um *link* para que você possa saber a que *commit* ele reverteu para.

Se chamarmos o código do *commit* resultante de A’ e utilizarmos o seguinte comando:

```bash
$ git diff A A'
```

Verificaremos que não obtivemos saída, ou seja, apesar de *commits* diferentes, eles são idênticos.

Espero que a dica de hoje seja útil nos *reverts* do dia a dia.
