Committed to the wrong branch?

Git cherry-pick (in detail)

Sakshi Shreya
7 min readMay 15, 2021

Recently, an incident happened with me in the office. I created two branches for fixing two bugs, say bug1 and bug2. But instead of fixing the bugs in the respective branches, I fixed them in the same branch bug1.

Fig-1: The situation

The situation looks something like this. Let’s reproduce the situation first. And then we’ll see how to fix it.

But before going forward, I wanted you to know that you can write in the comments section, if you feel that I need to explain how I am writing the git log command. I would love to write a new blog on it.

Let’s reproduce the situation

Step1: Let’s create a new git repository. I have just created a new folder and initialized git in this step. Notice, I am on the master branch right now. (see the blue text in brackets.)

Fig-2: Initialize repository

Step2: Create two files for the two bugs and write random text in them. And then commit those files. Note that I am still in master.

Fig-3: Commit the bug files

Step3: Create two branches for the two bugs.

Fig-4: Create two branches

Step4: Checkout to bug1 branch. Fix bug1. And commit.

Fig-5: Checkout to bug1 branch and commit the bug1 fix

Step5: Fix bug2 and commit. Note that I forgot to switch to the bug2 branch. I am still in bug1 branch.

Fig-6: Commit bug2 fix

Let’s show you how the commit graph looks like. I have attached both git-bash and git-GUI graphs. See whichever you are comfortable with.

Note: If you have never seen a git graph, please see the red-marked area in GUI and please follow that area throughout this blog. The graph is in reverse chronological order, means latest commits will come first.

Fig-7a: Git bash log of bug1 branch
Fig-7b: Git GUI log of all branches (see the red marked area)

Observe:

You can see that I have three branches.

  • master
  • bug1
  • bug2

master and bug2 are pointing to the same commit. bug1 has both the fixes.

Issue:

I want bug2 fix in the bug2 branch. But if I try to pull the whole bug1 branch in bug2, then bug1 fix will also be pulled along with bug2 fix. Since bug1 fix is done before bug2, it is not possible to delete that commit.

We need to find a way to only pull bug2 fix in the bug2 branch and delete that commit from bug1 branch.

Cherry-pick (pull bug2 fix only)

We first need to checkout to the bug2 branch.

Fig-8: Checkout to bug2 branch.

Copy the git SHA id for the commit that we want to cherry-pick. In our case, it is “dbb41c4”.

Note: Yellow text is the commit id. Copy the one that you want. I have copied the one for “Fix bug2” commit.

If you want to cherry-pick more commits, you can copy-paste all the commit ids in the below-mentioned command:

git cherry-pick <space-separated-commit-ids>

For example, for our case it is:

git cherry-pick dbb41c4
Fig-9a: Cherry-pick commit to bug2 branch | git bash log of bug2 branch
Fig-9b: git GUI log of all branches

In git-bash, you can see only master and bug2 branches, because right now we are on the bug2 branch and it doesn’t know where bug1 is (or it doesn’t know the history of bug1). But in git-GUI, you can clearly see all three branches.

Observe that the bug1 branch still has the bug2 fix commit. We have to delete that. But before deleting, let’s see what else we can do with cherry-pick.

Multiple commits in one cherry-pick

For fun, I took the two commit ids in reverse order.

Fig-10a: Cherry-pick commits to bug2 branch | git bash log of bug2 branch
Fig-10b: git GUI log of all branches

Edit commit message prior to committing

You would like to add -e or --editflag to your cherry-pick command.

git cherry-pick dbb41c4 -e

Following are the screens that you will see step-wise:

Fig-11.1: Vim editor screen after using -e flag

This is vim editor, for editing, you need to press i key first. Then you will enter into insert(edit) mode.

After that you can change the yellow text to your new commit message.

The lines starting with # are comments. You don’t need to bother about that.

Fig-11.2: After changing the commit message

Okay, what are the changes here that you can see:

  1. On the last line, you can see -- INSERT --. It is there because I am in insert mode.
  2. The yellow line has changed. I have changed that line to the new commit message.

After writing the new commit message, you need to move out of the insert mode. For that, press Esc key. You will notice that the -- INSERT -- line is blank now.

Then we have to save this commit and move out of vim. We need to enter :wq command for that. : means we are going to write a command now. w stands for ‘write’. q stands for quit. And you will see that you have come back to your familiar command-line interface.

Fig-11.3: After saving and quitting from vim editor

Graphs (Notice the new commit message):

Fig-12a: git bash log of bug2 branch
Fig-12b: git GUI log of all branches

Mention the commit from where this commit is cherry-picked

The flag for this is -x.

Fig-13a: Cherry-pick along with mentioning original commit id (see red marked area for original commit hash) | git bash log of bug2 branch

The commit message comes in the description of the cherry-picked commit message. It was not visible in the pretty format. So I have shown the long version of git log here.

Fig-13b: git GUI log of all branches (see red marked area for original commit hash)

Sign-off a commit

If your company, or the project you are working on requires you to sign-off a commit, and you use the -s or --signoff flag in your commit messages, then you can use the same flag here also.

Fig-14a: Cherry-pick along with sign-off (see red marked area for sign-off) | git bash log of bug2 branch

Again the commit message was not completely visible in pretty format, so I have shown the long version.

Fig-14b: git GUI log of all branches (see red marked area for sign-off)

Remove the commit from the first branch

We will do git reset here. But first, let’s move back to the bug1 branch.

Fig-15a: Checkout to bug1 branch | git bash log of bug1 branch

Notice that bug1 also doesn’t know about the history of bug2. That is why it is not showing that branch here.

Fig-15b: git GUI log of all branches

Copy the SHA id for ‘Fix bug1’ commit, because that is where we want this branch to point to. In our case, the id is 13a4534. We will reset our branch to that point.

Fig-16a: Revert back to bug1 fix | git bash log of bug1 branch
Fig-16b: git GUI log of all branches

And we are done here.

Other scenarios

What if bug2 was fixed before bug1?

Fig-17: Bug2 fixed before bug1

Or if bug2 fix was in between some bug1 fix commits.

Fig-18: Bug2 fixed between bug1 fixes

In these cases, cherry-picking step would have worked in the same way. But we would have to create a new branch for bug1 fix and cherry-pick all the commits related to bug1 in the new branch.

This is all that I have for now. If I ever find something new related to this topic, I will add it here.

You can follow me on Twitter, LinkedIn or Github for updates. If you have any doubts, you can comment below or message me on any of the above-mentioned links and I will try to resolve your doubts to the best of my ability.

--

--