January 26, 2020
Last week I was at work and suffering from some serious burn out and was horribly sleep deprived. My 2 year old was teething and had therefore made it impossible to get more than 2-3 hours of broken sleep the night before. I'd just wrapped a bug fix and planned to switch over to a feature branch with some other work I'd started on, delete the bug fix branch and continue with my other task. Unfortunately, in my brain-frazzled state, this is what actually happened: my PM walked over to my desk as I was preparing to checkout my feature branch, when our brief chat was over I totally lost where I was and what I had been planning on doing, remained on my bug fix branch, and ran
git delete -D tech/feature-branchon the branch that I wanted to keep. Moments later, this was me:
After a brief period of panic and berating myself for being so completely stupid, I told myself that there had to be some way to recover the branch that I had just deleted. I had made commits to that branch so surely it had to exist somewhere it the Git void right?
Creating a Feature Branch
Thankfully recovering a deleted branch is extremely simple but let's first take a step back to the beginning and create a branch from master.
I've created a new branch off master called
feature-branch. From there, I've made some changes, added those changes to the stage area and then committed them.
We can see a couple of things in the above screenshot:
- line 1: the commit message
- line 2: my feature-branch has been assigned a commit ID. What we see here is the shortened version of the ID.
- line 3: the number of files changed and that the change made was a deletion.
I then run
git log --oneline --graph --decorate --alland can see my commit in the logs with the shortened commit ID, that HEAD is pointing at master and feature-branch was created from there, and my commit message.
If we wanted to see the full commit ID, a git SHA-1 hash, we could simply run
And if we were to draw a diagram of my branches in git right now it might look something like this:
We can see the point in my git history where my feature branch was created from master and the 'some important change' commit was made. It's important to note that when I made that commit the master branch pointer automatically moved forward, keeping in mind that master is not a special branch in any way. It's just like all our other branches. We've merely deemed that master is the all important branch that feature branches are created from, and once work is complete, merged back into. You can make as many branches off master (or whatever you're all important branch is called) as you choose to, and the pointer will continue to move forward.
Right now my feature branch is safe and sound but let's imagine that, at some time in the coming days, while working on another branch I make the decision to clean up old branches, and run
git branch -D feature-branch. If I had run
git branch -d feature-branch, git would've warned me that the branch hadn't been fully merge, alerting me to the fact that I may want to keep that branch. Unfortunately, using the
-Dflag tells git that I don't care if it's not merged, just delete the damn thing.
This is exactly where I found myself last week but soon discovered there's an easy solution.
Recovering Deleted Branches
When you run
git branch -D <branch-name>is doesn't completely wipe the branch out of existence, it merely detaches the commit from the master branch, or whatever branch it was attached to, as seen in the below screenshot. Git still has a reference to any commit ID so you can still access that commit even though you ran a delete command.
If you run
git reflogyou'll see a long list of all the commits made in that repository. In the following screenshot you can see my 'some important change' commit, which was followed by me checking out onto the master branch.
All you need to do is find the commit message you're after, copy the ID then run
git checkout <commit ID>. When you do that, you'll see the following:
Git is alerting you to the fact that all you've done right now is check out onto the branch where that commit is but you are still in a detached state. If you were to make changes you could still stage them and commit them but the feature branch would still be floating out in git space all on its lonesome.
To reattach the branch to your master branch all you need to do is create a new feature branch. You can use the same name you had before or a completely new one e.g.
git checkout -b feature-branch. As soon as you do that, your new branch will be reattached to master, you can continuing making commits, and then merge the branch in when ready.
One final thing to note is that git commits do take up disk space so if you're working on a large project and lots of people are making commits to the repository, it's good hygiene to clean those out once in a while. Just try to make sure you don't delete all the commits because you never know if someone on your team just might need to run
git reflogto reattach a detached branch. Clearing out a commit history with a buffer of a month, or whatever works for you and your team, is probably the safest approach.