Undo git reset –hard with uncommitted files in the staging area

Question:

I am trying to recover my work. I stupidly did git reset --hard, but before that I’ve done only get add . and didn’t do git commit. Please help! Here is my log:

Is it possible to undo git reset --hard in this situation?

Answer:

You should be able to recover any files back that you added to the index (e.g, as in your situation, with git add .) although it might be a bit of work. In order to add a file to the index, git adds it to the object database, which means it can be recovered so long as garbage collection hasn’t happened yet. There’s an example of how to do this given in Jakub Narębski’s answer here:

However, I tried that out on a test repository, and there were a couple of problems – --cached should be --cache, and I found that it didn’t actually create the .git/lost-found directory. However, the following steps worked for me:

That should output all objects in the object database that aren’t reachable by any ref, in the index, or via the reflog. The output will look something like this:

… and for each of those blobs, you can do:

To output the contents of the file.


Too much output?

Update in response to sehe‘s comment below:

If you find that you have many commits and trees listed in the output from that command, you may want to remove from the output any objects which are referenced from unreferenced commits. (Typically you can get back to these commits via the reflog anyway – we’re just interested in objects that have been added to the index but can never be found via a commit.)

First, save the output of the command, with:

Now the object names of those unreachable commits can be found with:

So you can find just the trees and objects that have been added to the index, but not committed at any point, with:

That enormously cuts down the number of objects you’ll have to consider.


Update: Philip Oakley below suggests another way of cutting down the number of objects to consider, which is to just consider the most recently modified files under .git/objects. You can find these with:

(I found that find invocation here.) The end of that list might look like:

In which case you can see those objects with:

(Note that you have to remove the / at the end of the path to get the object name.)

Leave a Reply