Recuperando dados perdidos do git-stash

Olá senhores e senhoras! =]

Em meu primeiro post no Buteco Open Source vou demonstrar como recuperar dados perdidos do git-stash. Talvez salvando muitas horas de trabalho que poderiam ser perdidas acidentalmente. Na realidade o método demonstrado neste artigo pode ser utilizado para  recuperar qualquer objeto git perdido. Antes de mais nada, enquanto você estiver implementando alguma grande feature, quebre-a em pequenos pedaços e faça commits regularmente. Não é uma boa ideia permanecer muito tempo sem “comitar”. Tenha cuidado.

Vamos simular o cenário para mostrar o que você pode fazer quando perder dados do stash do git. Em um repositório para demonstração existe apenas um arquivo, main.c. Ele será utilizado para demonstrar o problema e a solução. Então, nosso repositório está assim agora:

missing_data_from_stash_01

e existe apenas um commit:

missing_data_from_stash_02

A primeira versão do arquivo é:

missing_data_from_stash_03

Vamos começar a codificar alguma coisa. Para este exemplo, não é necessário uma grande mudança, é apenas alguma coisa para colocar no git stash. Para isso, será adicionado apenas uma nova linha. O git-diff após a alteração é:

missing_data_from_stash_04

Agora, suponha que você tenha que realizar o pull de novas alterações de um repositório remoto e não quer realizar o commit de suas alterações por que elas não estão terminadas. Assim, você decide joga-las para o stash, baixar as alterações do repositório remoto e aplicar seu código novamente. Por isso, você executa o seguinte comando para mover suas alterações para o git stash:

git stash

Analisando o stash será possível ver que o comando funcionou como o esperado:

missing_data_from_stash_06

Neste momento, o código está em um local seguro e o branch master está limpo e o pull das mudanças pode ser realizado. Depois de ter atualizado o branch local com as alterações do branch remoto, é a hora de aplicar o código no master novamente. Vamos supor que acidentalmente você executa:

git stash drop

e depois é possível verifica, com o comando git stash list, que o stash limpou, e que o código foi removido e não foi aplicado no branch master. OMG! Quem poderá nos ajudar? Como você irá ver em breve, o git não apagou o objeto que contem as alterações. Ele apenas removeu a referência para ele. Para provar isso, pode ser usado o git-fsck. Este comando, verifica a conectividade e validade dos objeto na base de dados. Veja que no começo do nosso repositório foi executado o comando git-fsck e a saída foi:

missing_data_from_stash_07

Basicamente, git-fsck mostrou os objetos que são inalcançáveis ( flag –unreachable ). Como pode ser visto, ele não mostrou nenhum objeto. Depois que os elementos do stash foram dropados  o git-fsck mostrou:

missing_data_from_stash_08

Na última execução pode ser visto que existem três objeto inalcançáveis. Mas qual deles é o código perdido? Temos que procurar por ele, para isso podemos usar o comando git-show para visualizar o que é cada objeto.

missing_data_from_stash_09

Ai está! O ID 95ccbd927ad4cd413ee2a28014c81454f4ede82c é a alteração que estávamos procurando e temos que recuperá-lo! Uma possível solução é fazer o checkout do ID em um novo branch ou aplicar o commit diretamente. Neste exemplo será utilizado o git-stash para aplicar o commit no branch master novamente.

git stash apply 95ccbd927ad4cd413ee2a28014c81454f4ede82c

É importante relembrar, git executa seu garbage collector (gc) periodicamente. Após a execução do gc não será mais possível ver os objetos inalcançáveis.

Referência:

git-fsck

git-stash