Commit Regularly…Recovering Staged Git Changes.

Git Logo

Commit regularly…that is a lesson learnt the hard way for me today.

I was almost, going into a depression after loosing 3 days work. To add salt to the injury, it was some optimization work that I had very little idea about when I started, was expected ASAP since we were supposed to be having a release the next day and involved a huge amount of quality work and code.

So as I am finalizing on the changes and structuring the commit message, I remember I saw something that needs to be fixed. As I was conducting a search to ensure some redundant code was removed and replaced with inherited functionality, I realized that some instances of the redundant code still existed. On checking out, I found that at some point in the past, I had created a duplicate of the project with an aim of profiling the application using different environments, pypy3 and python3, and had left the folder existing in parent/working folder of the project even though I had created another branch for it in the remote git repository and this is where the redundant code existed.

My resolution was to pull the pypy3 implementation branch(from “duplicate” folder) into the original folder/repository and delete its folder from my local machine. This is where I did the first mistake that would really cost me.

I pull the pypy3 implementation branch even though I am in the python3 branch and it is immediately merged into the python3 branch. I assumed since you could push another branch to its remote equivalent while on another branch, then I could pull the pypy3 remote implementation branch into the pypy3 local implementation branch while on python3 implementation branch.

With pypy3 implementation branch merged into working branch and unstaged changes, I cannot git reset --hard to eliminate the unrequired changes. I decide to backup everything first in a new branch so that in-case of anything, if I loose the uncommitted changes in the working branch, then I would still have them in the backup branch. So I git checkout -b into a new branch and the unstaged changes flow to the new branch. I stage them for a commit thinking that if I go back to the python3 implementation branch the staged changes would still remain in the backup branch waiting for a commit but I am wrong.

I immediately checkout into the python3 implementation branch and git reset --hard to eliminate the changes introduced by merge of pypy3 implementation branch into python3 implementation branch and that is how I loose all my work that I have been spending a lot of time working on.

With no idea of how to undo the hard reset, I set out to find if it is possible from the internet. I spend quite some time doing this and come up with nothing. From my research as per this time, only commits can be recovered after a hard reset. Since I have been using atom as my text editor, I also consider recovering the changes through atom but the recovery files are non existent. Just as I begin to get depressed, I remember to whisper a prayer and after the prayer, I land on a Stack Overflow thread that would be my source of joy for the day.

Given that I had staged the changes for a commit, on loosing the changes they can be recovered using git fsck --lost-found that creates a lost-found sub-directory in the .git directory and writes dangling changes, commits and tags to it. To retrieve the files I use git show <blob hash>to check out the contents of the individual found files and recover them.