Committed to the wrong branch?
Git cherry-pick (in detail)

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.

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.)

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.

Step3: Create two branches for the two bugs.

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

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

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.


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.

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


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.


Edit commit message prior to committing
You would like to add -e
or --edit
flag to your cherry-pick command.
git cherry-pick dbb41c4 -e
Following are the screens that you will see step-wise:

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.

Okay, what are the changes here that you can see:
- On the last line, you can see
-- INSERT --
. It is there because I am in insert mode. - 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.

Graphs (Notice the new commit message):


Mention the commit from where this commit is cherry-picked
The flag for this is -x
.

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.

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.

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

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

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

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.


And we are done here.
Other scenarios
What if bug2 was fixed before bug1?

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

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.