Git: nem tudo está perdido

Quem já fez um reset --hard e depois percebeu que voltou mais do que devia? Humm, tá bom, eu fiz! Semana passada fui reverter algumas mudanças locais que commitei em uma branch do Alura, mas acabei resetando um commit a mais. É claro que eu só percebi isso depois de dar um git push.

A pergunta foi: e agora? O sentimento foi: medo. Mas a verdade é que se você commitou, no geral, da pra recuperar. Nesse post vou mostrar a forma que eu resolvi, que foi bem simples, e mais algumas possibilidades legais que acabei aprendendo no meio do caminho.

Entendendo o problema na prática

Pra reproduzir o acontecido, vou dar um git log na master do repositório do Alura e um reset --hard voltando a apontar pro penúltimo commit. Repara que tem um commit meu, adicionando um alarme de 80% de CPU em nosso servidor, e depois do reset a master volta a apontar pro commit do Philippe Ehlert, que antecedia:

Pronto, agora é só fazer um push -f origin master e se arrepender 2 segundos depois.

Em busca do commit perdido

A notícia boa é que mesmo que você tenha feito um reset, o commit continua lá… ele não é apagado! Ou seja, você pode recuperar qualquer commit se você souber o SHA1 dele. Se você não está acostumado com esse termo, SHA1 nada mais é do que esse hash bonitão (único) que identifica um commit:

exemplo de SHA1

Mas como eu vou saber o SHA1 se eu já fiz um reset e ele não aparece mais no log? A resposta é simples: toda mudança que você faz na HEAD de uma branch fica registrado em um lugar conhecido como reflog, que pode ser consultado com o comando git log -g:

Repara que primeiro eu fiz um git log normal, meu commit não estava lá… depois um git log -g e voilà, tenho o registro de tudo o que aconteceu na minha branch. Legal, não acha? O reflog tem muito mais informações que podem ser úteis, se você for curioso como eu, já deve estar googlando pela sua documentação.

Voltando o commit pra master

Agora que eu já tenho o SHA1 do meu commit eu posso, entre outras opções, fazer um cherry-pick desse commit de volta pra master. Não tem segredo, basta rodar git cherry-pick [SHA1] e pronto:

Ufa, problema resolvido.

Essa é uma regra valiosa do Git: se você commitou alguma coisa, provavelmente dá pra recuperar. Se você não commitou, bem… já foi! Por isso é importante fazer commit e se possível push de tudo com a maior frequência possível, falamos bastante disso no curso de Git do Alura e no curso de práticas ágeis daqui da Caelum.

E você, o que mais tem feito de legal com Git? Já perdeu algum commit e não conseguiu recuperar?

9 Comentários

  1. Icaro 02/05/2016 at 11:29 #

    sei que é meio off-topic, mas gostaria de mencionar o fato de que uma grande maioria tem migrado pro git nos ultimos anos mas ainda adotando um trabalho predominantemente centralizado, o que diminui bastante os beneficios de seu uso e o torna até mesmo mais enfadonho que as opções centralizadas anteriores. alguns argumentos sobre o github e tal, mas isso nao é merito do modelo, ha hosts equivalentes pra outros modelos de versionamento, distribuidos ou nao

  2. Rodrigo Turini 02/05/2016 at 12:04 #

    Oi Icaro. Sem dúvida ainda podemos explorar bastante os benefícios do git e outros.

    De forma geral, essas ferramentas e técnicas não são unânimes. O ideal é que você encontre as técnicas que funcionam melhor na realidade do seu time.

  3. Carlos Osés 04/05/2016 at 01:29 #

    Excelente dica. O reflog realmente salva vidas. Conhecer a fundo as funcionalidades do git é tão essencial quanto saber programar.

  4. Rodrigo Turini 04/05/2016 at 01:44 #

    É verdade, Carlos!

    Uma forma legal também de ver o reflog é com o comando “git reflog show”.

    Ele mostra uma versão abreviada, de uma linha, desse log.

  5. Raphael Lacerda 10/05/2016 at 14:14 #

    Show Rodrigo!

    bacana demais!

    não conhecia o git log -g

  6. Anderson Silva 11/05/2016 at 22:47 #

    Essa possibilidade de corrigir um descuido é realmente muito importante, já aconteceu de eu excluir um commit resultado de um rebase, e na hora eu entrei em desespero, mas o dia foi salvo por um colega já experiente em git e que sabia usar o reflog.

    Parabéns pela dica!

  7. Rodrigo Turini 12/05/2016 at 09:49 #

    Valeu, Lacerda e Anderson!

    Eu percebi que o reflog acaba virando rotina depois de salvar sua vida pela primeira vez 🙂

  8. Lucas Ferreira 06/06/2016 at 18:54 #

    Muito útil 😀

  9. Derrick 07/06/2016 at 23:54 #

    Massa e muito útil. Obrigado Rodrigo!

Deixe uma resposta