Recovering your lost uncommitted git changes after hard reset
October 8, 2023 · 3 min read

It is a good practice to not keep a lot of untracked changes in your code, but I'm assuming it's one of those days where you are deep into refactoring something and you have to quickly switch branches because something important has come up or production broke down and you have to send out a quick patch.

Such is startup life. Sometimes things go wrong.

One day I had to switch branches and instead of typing out git stash and then git switch, like any other power user of the terminal, I kept pressing the up arrow to go back to that one command I know exists in the history; but this time, I selected and executed a wrong one, a very very wrong one - rm -rf .

I started panicking, because I lost all the changes I was doing for that day - nearly 50 files. Now if you ask me why would I be stupid enough to keep such a large amount of un-committed changes - I don't have an answer. But, saner thoughts prevailed and I completed the task at hand - an important bug fix that had to be pushed out and decided to worry problem the other problem later.

Now, problem at hand - how do I get back my changes? I spent a lot of time refactoring the code and I did not want to spend another half a day redoing them. Did a couple of Google searches and got nowhere with Stackoverflow's suggestion of using reflogs. Then started doing the hard part of going through the entire git documentation and came across fsck --lost-found.

If at any point in time, you have "staged" your changes by doing a git add, but never bothered with actually committing it, you're in luck. git would have automatically packed them into an object for it's internal use.

Running a simple git fsck --lost-found will give you a list of dangling blobs or trees that are these packed objects.

Checking object directories: 100% (512/512), done.
dangling tree e430d46757b8c02f71914f5ce8384ae858a29764
dangling blob aab3a57ee0c864e6c523018c4454858c04a69c4d
dangling tree be564476e2070f6dec19bab524e3ba608c745ae1
dangling blob ee81d0743071b52b1beb4522721f489fc5905fef
dangling tree f853461fd9badc4a4f35f4b1cfb25e598873b1fd

We want to concentrate on trees.

One of these contains the changes that I worked on, so to view them, a git show {hash} prints out the diff. Once verified that the change I want exists, a simple git checkout {hash} will checkout that particular hash which can be applied to my working branch later :)