Recovering your Git repository after doing a “git reset –hard”

There are many stupid people in this world. This guy is another one of them:
Picture of Xerxes Battiwalla

Yes that’s right, yours truly really screwed up this time.

For future reference (and in a nutshell), git checkout is not the same as git reset, particularly when you throw in the hard option. I know this now, and in fact I knew it when i accidentally blew away half my repository – didn’t make the end result any less pleasing.

Here’s the gitk output of what my tree looked like before the wipe:

Full project history from gitk

I was intending to checkout a previous revision of the repo to show how some code had evolved over time. Normally I would do this from the command line, but this time I (crazily) chose to use (the very disabled) gitk to do this, and blindly chose the “hard” option without thinking. So what I was left with was a very lacking repository and even sorely bruised ego. Goodbye repo history! It’s been nice knowing you….

Wiped Repository

Thanks to the ever-knowledgeable davesquared, there’s a way to recover your git repo once you bone yourself. If you escape the clutches of the gitk demon, the command line interface gives you a better level of control (and content which is crawlable by search engines 😉 )

It turns out that until the repository is cleaned (git gc) and stale objects are cleared, the repo still has the necessary content stored, it’s just not visible. (if the following block looks terrible in your renderer, click through the link to read it properly.)

xerxes@laptop /d/source/dotnet/CodeKatas/.git/logs (GIT_DIR!)
$ cat HEAD
0000000000000000000000000000000000000000 f167fd4068e4b92134964e073f2e69a0cc8fced9 Xerxes  1250928395 +1000 commit (initial): Initial commit of binary search
f167fd4068e4b92134964e073f2e69a0cc8fced9 dd31afc8d793aaa952e032a77675b8e67f6b26bc Xerxes  1251007341 +1000 commit: Removedbin/obj from source control
dd31afc8d793aaa952e032a77675b8e67f6b26bc 0642a5e64a513f8949f7aa9e1d35a298fb713bfc Xerxes  1251007422 +1000 commit: removed.suo from source control
0642a5e64a513f8949f7aa9e1d35a298fb713bfc 0cf0929cfb9a31707b2ae937f0c6e73bd9e5bcb9 Xerxes  1251007479 +1000 commit: Implemented first binary tree implementation. it is shit
0cf0929cfb9a31707b2ae937f0c6e73bd9e5bcb9 6c27c54370bf2b79369dc5ef02ef7338bbf2865a Xerxes  1251010817 +1000 commit: Refactored first implementation to remove unnecessary elements
6c27c54370bf2b79369dc5ef02ef7338bbf2865a 937fcb1c36bf437e0df11847ee579ca60151144d Xerxes  1251021898 +1000 commit: removedresharper settings file from project
937fcb1c36bf437e0df11847ee579ca60151144d b12a95ea3c636615345559979d3fc0e93fecc0bc Xerxes  1251022036 +1000 commit: Rewritten first implementation of b-search to get practice.
b12a95ea3c636615345559979d3fc0e93fecc0bc f57503a6116822c9632e6b4dc6cb423640c6a152 Xerxes  1251028214 +1000 commit: 3rd implementation of binary search using shifted bounds.
f57503a6116822c9632e6b4dc6cb423640c6a152 be510f0f88baa38d8d2e645f568405d052f5bb14 Xerxes  1251028265 +1000 commit (amend):Another rewrite of binary search using shifted bounds.
be510f0f88baa38d8d2e645f568405d052f5bb14 2c0b21e7aea2dd27fc7281d1a20a887e2e1f3d0d Xerxes  1251090393 +1000 commit: Yet another re-write of the shifted boundary method.
2c0b21e7aea2dd27fc7281d1a20a887e2e1f3d0d d2a23e1cad8b36de1361700b89733a3b08401e2c Xerxes  1251253854 +1000 commit: Moved BinaryTree project to top-level folder
d2a23e1cad8b36de1361700b89733a3b08401e2c 4e8bd70336e89f9000f29553d53d98cb568bc809 Xerxes  1251253901 +1000 commit: Added nunit to the list of dependencies
4e8bd70336e89f9000f29553d53d98cb568bc809 551c754f27f10826dab43c50d8a3151b7e2740f5 Xerxes  1251253922 +1000 commit: Implemented FizzBuzz
551c754f27f10826dab43c50d8a3151b7e2740f5 11884f5935c85d4ec1497fe3a8eb39211d731fdc Xerxes  1251269688 +1000 commit (amend):Moved parameters onto FizzBuzz method and out of constructor
11884f5935c85d4ec1497fe3a8eb39211d731fdc cbda7a8c68c88900eb1c58ab7bf613bad26892ad Xerxes  1251269732 +1000 commit (amend):Implemented FizzBuzz solution
cbda7a8c68c88900eb1c58ab7bf613bad26892ad b40c951696a2d11854fce6a9fca1be9fc436e61b Xerxes  1251341643 +1000 commit: Anotherre-implementation of the shifted-boundaries method
b40c951696a2d11854fce6a9fca1be9fc436e61b b2c2a8b103aa43dac8e443cfc866fa35f9ffb048 Xerxes  1251341967 +1000 commit: RenamedBinarySearch to ShiftedBoundariesBinarySearch
b2c2a8b103aa43dac8e443cfc866fa35f9ffb048 30a224eb40c441df8a18b06eeb68af47a86bc37f Xerxes  1251344036 +1000 commit: Implemented RecursiveBinarySearch (badly). requires refactor
30a224eb40c441df8a18b06eeb68af47a86bc37f 0fbf8ace753f408b0e972b593e2b6a03dd2d0354 Xerxes  1251345463 +1000 commit: CreatedTreeNode Search
0fbf8ace753f408b0e972b593e2b6a03dd2d0354 0cf0929cfb9a31707b2ae937f0c6e73bd9e5bcb9 Xerxes  1251345505 +1000 0cf0929cfb9a31707b2ae937f0c6e73bd9e5bcb9: updating HEAD
0cf0929cfb9a31707b2ae937f0c6e73bd9e5bcb9 2c0b21e7aea2dd27fc7281d1a20a887e2e1f3d0d Xerxes  1251345635 +1000 checkout: moving from master to 2c0b2

xerxes@laptop /d/source/dotnet/CodeKatas/.git/logs (GIT_DIR!)
$ 

The beauty here is that the log has kept full record of all the SHAs for each commit in the repo. NOW i’m able to reset my master back to the appropriate commit by using the SHA-1 hash. So i checked out onto the master branch and issued:

xerxes@laptop /d/source/dotnet/CodeKatas (master)
$ git reset --hard 0fbf8ace753f408b0e972b593e2b6a03dd2d0354 

and that reset my master back to the right revision, thereby restoring my history, code and sanity.

nb: i have taken some of these screenshots trying to reproduce after the event, so they might look a little doctored. Despite this, the findings and end results are the same.

2 comments

  1. All you need to do after a git reset –hard that you did by accident is:

    git reset –hard @{1}

    That will restore your branch to the previous state.

Leave a Reply to Jason LeBrun Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>