7

O que fazer após aplicar um rebase errado

Olá, caro leitor,

Decidi compartilhar esta experiência porque ela pode ser útil, principalmente em tempos em que LLMs geram muito código e realizam refatorações de sistemas rapidamente. Misturado com necessidades de alta criticidade, é fácil cometer alguns erros, como o da breve história a seguir.

Depois de dois dias trabalhando em uma refatoração de código que não possuía camadas bem definidas, envolvendo uma biblioteca wrapper para acesso ao banco de dados e o código principal que expunha alguns endpoints, eu movi toda a lógica de parsing do banco para o wrapper e deixei as regras de negócio e validações no código principal.

Somado a isso, havia um uso excessivo de funções da biblioteca Ramda para gerar os payloads de resposta, sem utilizar o padrão Data Transfer Object (DTO). Isso tornava muito difícil garantir que o código estivesse correto sem quebrar algum tipo de resposta.

Com o contexto explicado, vamos à situação principal.

Quando terminei as validações e os testes unitários, precisei sincronizar meu código com a branch principal. Então executei o seguinte comando, resolvi os conflitos em modo rebase e foi aí que tudo começou a dar errado:

git pull origin main

Durante a resolução dos conflitos, não percebi todas as alterações que estavam sendo aplicadas. Apenas corrigi os conflitos, aceitei o rebase e abri o Pull Request.

Isso aconteceu no final do dia, então não me julgue (risos).

Vamos admitir: foi um erro de iniciante!

Como resolvi

Perguntando para uma IA generativa como eu poderia reverter esse problema de rebase, descobri algo muito interessante: o comando abaixo.

git reflog --date=iso

Reflog significa Reference Log. Ele funciona como um log de auditoria do ponteiro HEAD: toda alteração nesse ponteiro é registrada.

Algumas características importantes:

  • O histórico do reflog expira após aproximadamente 30 a 90 dias.
  • Ele existe apenas na sua máquina local.
  • As informações do reflog não são enviadas para o repositório remoto.

O resultado do comando se parece com a imagem abaixo:

Resultado do comando

Com esses registros em mãos, basta criar uma nova branch apontando para o commit desejado.

No meu caso, criei uma nova branch utilizando o seguinte comando:

git switch -c fix/rollback-before-rebase f23839f

E isso salvou o meu dia!

Conclusão

O git reflog é uma ferramenta extremamente útil para recuperar estados anteriores do repositório quando algo dá errado, especialmente após rebases, resets ou outras operações que alteram o histórico.

Se você já passou por uma situação parecida, vale a pena conhecer e dominar esse comando.

Obrigado pela leitura! E me conte o que achou.


Carregando publicação patrocinada...
2

Muito bom! O reflog é muito útil mesmo e pode nos salvar dessas situações em que um branch parece ter "sumido".

Pra complementar, tem esse post que explica em mais detalhes o reflog.

Quanto a "O histórico do reflog expira após aproximadamente 30 a 90 dias", na verdade é assim: 30 e 90 dias são os valores default para duas configurações diferentes.

Uma é o gc.reflogExpireUnreachable (cujo default é 30 dias), e diz respeito à entradas do reflog que não são alcançáveis a partir do branch atual. A segunda é gc.reflogExpire (cujo default é 90 dias), e é para qualquer entrada do reflog.

Mas vc pode mudar esses valores. Por exemplo, se quiser aumentar para 180 dias:

git config --global gc.reflogExpire 180.days

Por fim, vale lembrar que as entradas que já expiraram só são removidas quando o Git roda o seu GC. E o GC geralmente executa por debaixo dos panos quando vc roda outros comandos, como commit, merge, entre outros. Claro que vc também pode rodar diretamente git gc ou git reflog expire, mas não é algo estritamente necessário.

1

Bacana demais, muito obrigado pela contribuição, acho que os valores defaults de fato são suficientes para a maioria dos casos.

É incrível ver como na correria do dia a dia, ficamos apenas na superfície do conhecimento.