git ready

dicas diárias para o noob ao guru
por Nick Quaranto, traduzido pela comunidade RailsBr

recuperando commits perdidos

publicado em 17 Jan 2009

Então, você fez um git reset --hard HEAD^ e jogou fora o seu último commit. Bem, acontece que você realmente precisa dessas mudanças. Você nunca será capaz de implementar esse algoritmo perfeitamente, de modo que você obtenha o que precisa de volta. Não tema, pois o GIT ainda deve ter o seu commit. Quando você faz um reset, o commit que você jogou fora passou para um estado de “pendente”. Ele ainda esta no datastore do GIT, aguardando que a próxima execução do ‘garbage collection’ limpe tudo. Portanto, caso você não tenha executado um git gc, você ainda poderá restaurá-lo.

Por exemplo, eu estou trabalhando com o código deste blog. Para executarmos os seguintes códigos:

$ git show-ref -h HEAD
  7c61179cbe51c050c5520b4399f7b14eec943754 HEAD

$ git reset --hard HEAD^
  HEAD is now at 39ba87b Fixing about and submit pages so they don't look stupid

$ git show-ref -h HEAD
  39ba87bf28b5bb223feffafb59638f6f46908cac HEAD

Então o nosso HEAD foi apoiado por um commit. Neste ponto se você quiser voltar pode apenas fazer um git pull, mas não estamos partindo do princípio de que só o nosso repositório local sabe sobre o commit. Temos o SHA1 do commit para que possamos trazê-lo de volta. Podemos provar o que o GIT ainda sabe sobre commit com o comando fsck:

$ git fsck --lost-found
  [... some blobs omitted ...]
  dangling commit 7c61179cbe51c050c5520b4399f7b14eec943754

Você também pode ver o que o GIT ainda sabe sobre o commit utilizando o comando reflog:

$ git reflog
  39ba87b... HEAD@{0}: HEAD~1: updating HEAD
  7c61179... HEAD@{1}: pull origin master: Fast forward
  [... lots of other refs ...]

Então, agora temos o nosso SHA1: 7c61179. Se quisermos obte-lo novamente e aplicá-lo de volta ao nosso branch atual, então devemos fazer um git merge para recuperar o commit:

$ git merge 7c61179
  Updating 39ba87b..7c61179
  Fast forward
    css/screen.css |    4 ++++
    submit.html    |    4 ++--
    2 files changed, 6 insertions(+), 2 deletions(-)

Este comando irá trazer as suas alterações perdidas de volta e se certificar de que o HEAD esta apontando para o commit. A partir daqui você pode continuar trabalhando normalmente! Você também pode validar o SHA1 de um novo branch, mas realmente um merge é a maneira mais facíl e rápida para restaurar um commit perdido desde que você tenha o hash. Se você souber algum outro caminho nos informe nos comentários!

Se você quiser mais opções sobre o que fazer nessa situação, Mathieu Martin’s fez um guia ilustrado para recuperar commits perdidos no GIT.