Skip to main content

How To Recover Lost Git Branches

Daniel, at work, ran into a problem of accidentally removing a branch he had just created and made a commit to, thus loosing the days work. This was actually the fault of our internal scripts to manage the branching and merging policy we've set up. By "internal" I mean that I wrote them and it was my fault his whole day of work was gone, so that left it up to me to figure out how to repair the situation and salvage the current commit back from the ether. I thought it might be good to document, in the case that anyone else needs to do this.

This works in the case of branch A existing and branch B being removed after a single commit on it and branch B being from A. This means we know commit A and we need to find an unnamed commit, what was B, to recover it.

I can demonstrate the recovery process with a simple transcript.

ironfroggy:/tmp ironfroggy$ mkdir A
ironfroggy:/tmp ironfroggy$ cd A
ironfroggy:/tmp/A ironfroggy$ git init
Initialized empty Git repository in .git/
ironfroggy:/tmp/A ironfroggy$ cat >> test
a b c
ironfroggy:/tmp/A ironfroggy$ git add test
ironfroggy:/tmp/A ironfroggy$ echo "commit 1" | git commit -m test
Created initial commit 5b2401e: test
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 test
ironfroggy:/tmp/A ironfroggy$ cat >> test
1 2 3
ironfroggy:/tmp/A ironfroggy$ git add test
ironfroggy:/tmp/A ironfroggy$ echo "commit 2" | git commit -m test
Created commit 08217dc: test
1 files changed, 1 insertions(+), 0 deletions(-)
ironfroggy:/tmp/A ironfroggy$ git reset --hard HEAD^
HEAD is now at 5b2401e... test
ironfroggy:/tmp/A ironfroggy$ git reflog show master
5b2401e... master@{0}: reset --hard HEAD^
08217dc... master@{1}: commit: test
ironfroggy:/tmp/A ironfroggy$ git log master
commit 5b2401e38d400c3039a53a036f2d98f75d544056
Author: Calvin Spealman
Date: Sun Dec 2 13:27:25 2007 -0500

test
ironfroggy:/tmp/A ironfroggy$ git log 08217dc
commit 08217dc6ef8f8117d6c9e4bca6fe7f18f78559b6
Author: Calvin Spealman
Date: Sun Dec 2 13:28:01 2007 -0500

test

commit 5b2401e38d400c3039a53a036f2d98f75d544056
Author: Calvin Spealman
Date: Sun Dec 2 13:27:25 2007 -0500

test
ironfroggy:/tmp/A ironfroggy$ git merge 08217dc6ef8f8117d6c9e4bca6fe7f18f78559b6
Updating 5b2401e..08217dc
Fast forward
test | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
ironfroggy:/tmp/A ironfroggy$ cat test
a b c
1 2 3


The red line is the dangerous move that lost your commit. Now, nothing is actually removed from the repository, except for when you perform a garbage collection, so I knew we could recover this somehow. After a short time looking through the docs and asking a question or two on IRC, I arrived at the solution. There are logs kept on the changes that happen to refs (or branches), so I could use that to see the log of when that commit happened. You can see that and the commit the follows when the reset occurs and undoes our commit. The commit id is in the short version, but if we look at the log of that commit, we get the full ID and can simply merge it back into our branch. A very clean solution, indeed.

For Daniel This Means...

He didn't loose his whole days work, but he should be doing local commits more often so that any problems with our scripts can't show up in the first place. At least the work was recovered, and in short time. He is saved, for one more day at least, from being a disgruntled co-worker.

For Git This Means...

I'd love to contribute, so I'm thinking the git-fsck command needs something that can do this for you. Some operation to locate child commits would be really useful in these situations. Once again, I'm very happy with the move to Git.

Comments

jnareb said…
Actually the post is not how to recover lost git branches (you would lost branches together with reflog after doing 'git branch -D [branchname]'), but how to recover lost history (like for example 'git reset --hard HEAD^'). To recover lost branches you would need 'git fsck --lost-found'...
Ahsan said…
Thanks man, This post saved me 3 days of hard work !
Anonymous said…
Even better, if you don't know the commit's hash code, you can access it via HEAD@{1}, or even master@{yesterday}.
Anonymous said…
I owe you a beer
Holy crap, thank you thank you!
Anonymous said…
@jnareb: woah, thank you for sharing, it saved my night!

Popular posts from this blog

Respect and Code Reviews

Code Reviews in a development team only function best, or possible at all, when everyone approaches them with respect. That’s something I’ve usually taken for granted because I’ve had the opportunity to work with amazing developers who shine not just in their technical skills but in their interpersonal skills on a team. That isn’t always the case, so I’m going to put into words something that often exists just in assumptions.
You have to respect your code. This is first only because the nature and intent of code reviews are to safeguard the quality of your code, so even having code reviews demonstrates a baseline of respect for that code. But, maybe not everyone on the team has the same level of respect or entered a team with existing review traditions that they aren’t acquainted with.
There can be culture shock when you enter a team that’s really heavy on code reviews, but also if you enter a team or interact with a colleague who doesn’t share that level of respect for the process or…

CARDIAC: The Cardboard Computer

I am just so excited about this.


CARDIAC. The Cardboard Computer. How cool is that? This piece of history is amazing and better than that: it is extremely accessible. This fantastic design was built in 1969 by David Hagelbarger at Bell Labs to explain what computers were to those who would otherwise have no exposure to them. Miraculously, the CARDIAC (CARDboard Interactive Aid to Computation) was able to actually function as a slow and rudimentary computer. 
One of the most fascinating aspects of this gem is that at the time of its publication the scope it was able to demonstrate was actually useful in explaining what a computer was. Could you imagine trying to explain computers today with anything close to the CARDIAC?

It had 100 memory locations and only ten instructions. The memory held signed 3-digit numbers (-999 through 999) and instructions could be encoded such that the first digit was the instruction and the second two digits were the address of memory to operate on. The only re…

How To Care If BSD, MIT, or GPL Licenses Are Used

The two recent posts about some individuals' choice of GPL versus others' preference for BSD and MIT style licensing has caused a lot of debate and response. I've seen everything as an interesting combination of very important topics being taken far too seriously and far too personally. All involved need to take a few steps back.

For the uninitiated and as a clarifier for the initiated, we're dealing with (basically) three categories of licensing when someone releases software (and/or its code):
Closed Source. Easiest to explain, because you just get nothing.GPL. If you get the software, you get the source code, you get to change it, and anything you combine it with must be under the same terms.MIT and BSD. If you get the software, you might get the source code, you get to change it, and you have no obligations about anything else you combine it with.The situation gets stickier when we look at those combinations and the transitions between them.

Use GPL code with Closed S…