Recovering Lost Commits with git reflog and reset

When I first setup this blog I took the opportunity to try out Git, and imported the source of the blogging software into a Git repository. The thinking was that if I needed to patch the blog software that I'd have a fairly trouble free upgrade path, merging the upstream changes straight into my branch.

All went well until, after several hours of work, I lost everything...

Breaking everything

Whilst experimenting with various git commands that I didn't fully understand I managed to lose a lot of commits. I should have taken a backup, but I'm quite glad I didn't as I might not have learnt that git was making my backup for me.

Though I forget how I achieved it, all my work appeared to have vanished and when I typed git log there was no sign of missing commits. My initial reaction was that I should just start again. I'd done it all once before---how hard could it be?

Luckily I paused for a moment and logged on to the #git channel on irc.freenode.net, where I learnt this little nugget (thanks to a very helpful chap who goes by the name of Eridius).

Reviewing lost commits

The reflog command will give you a good history of what's been happening on the head of your branches. Run it, then find the line that refers to the state that you want to get back to:

$ git reflog
... snip ...
cf42fa2... HEAD@{84}: checkout: moving to master
73b9363... HEAD@{85}: commit: Don't symlink to themes on deployment.
547cc1b... HEAD@{86}: commit: Deploy to effectif.com web server.
1dc3298... HEAD@{87}: commit: Updated the theme.
18c3f51... HEAD@{88}: commit: Verify with Google webmaster tools.
26fbb9c... HEAD@{89}: checkout: moving to effectif

The latest entries appear at the top. You can work out which branch each change was made on by looking out for lines that say "checkout: moving to ...". Commits 88 through to 85 (they're numbered in the second column of the output) were the commits that I'd lost; all I needed to do was to get them back.

Reverting a branch to an earlier state

In short, you need to switch to the correct branch ("effectif" in my case) and then do a hard reset. The --hard options sets the HEAD of the current branch back to the commit that you specify:

git checkout effectif
git reset --hard 73b9363

It's like time travel, only cheaper. Have a poke around the git-reset(1) man page for other options.

I love feedback and questions — please get in touch on Twitter or leave a comment.

Published on in Git