A Guide To Undoing Mistakes With Git (Part 2)

Articles on Smashing Magazine — For Web Designers And Developers A Guide To Undoing Mistakes With Git (Part 2)

In this second part of our series on « Undoing Mistakes with Git », we’ll bravely look danger in the eye again: I’ve prepared four new doomsday scenarios — including, of course, some clever ways to save our necks! But before we dive in: take a look at the check out previous articles on Git for even more self-rescue methods that help you undo your mistakes with Git!

Let’s go!

Recovering a Deleted Branch Using the Reflog

Have you ever deleted a branch and, shortly after, realized that you shouldn’t have? In the unlikely event that you don’t know this feeling, I can tell you that it’s not a good one. A mixture of sadness and anger creeps up on you, while you think of all the hard work that went into that branch’s commits, all the valuable code that you’ve now lost.

Luckily, there’s a way to bring that branch back from the dead — with the help of a Git tool named « Reflog ». We had used this tool in the first part of our series, but here’s a little refresher: the Reflog is like a journal where Git notes every movement of the HEAD pointer in your local repository. In other, less nerdy words: any time you checkout, commit, merge, rebase, cherry-pick, and so on, a journal entry is created. This makes the Reflog a perfect safety net when things go wrong!

Let’s take a look at a concrete example:

$ git branch  * feature/login  master  

We can see that we currently have our branch feature/login checked out. Let’s say that this is the branch we’re going to delete (inadvertently). Before we can do that, however, we need to switch to a different branch because we cannot delete our current HEAD branch!

$ git checkout master  $ git branch -d feature/login  

Our valuable feature branch is now gone — and I’ll give you a minute to (a) understand the gravity of our mistake and (b) to mourn a little. After you’ve wiped away the tears, we need to find a way to bring back this branch! Let’s open the Reflog (simply by typing git reflog) and see what it has in store for us:

Here are some comments to help you make sense of the output:

  • First of all, you need to know that the Reflog sorts its entries chronologically: the newest items are at the top of the list.
  • The topmost (and therefore newest) item is the git checkout command that we performed before deleting the branch. It’s logged here in the Reflog because it’s one of these « HEAD pointer movements » that the Reflog so dutifully records.
  • To undo our grave mistake, we can simply return to the state before that — which is also cleanly and clearly recorded in the Reflog!

So let’s try this, by creating a new branch (with the name of our « lost » branch) that starts at this « before » state SHA-1 hash:

$ git branch feature/login 776f8ca  

And voila! You’ll be delighted to see that we’ve now restored our seemingly lost branch! 🎉

If you’re using a Git desktop GUI like « Tower », you can take a nice shortcut: simply hit CMD + Z on your keyboard to undo the last command — even if you’ve just violently deleted a branch!

Luckily, these types of problems can be easily corrected. Let’s roll up our sleeves and get to work.

The first step is to switch to the correct destination branch and then move the commit overusing the cherry-pick command:

$ git checkout feature/login  $ git cherry-pick 776f8caf  

You will now have the commit on the desired branch, where it should have been in the first place. Awesome!

But there’s still one thing left to do: we need to clean up the branch where it accidentally landed at first! The cherry-pick command, so to speak, created a copy of the commit — but the original is still present on our long-running branch:

This means we have to switch back to our long-running branch and use git reset to remove it:

$ git checkout main  $ git reset