Attempting to Apply Cherry-Pick

Learn why a cherry-pick might not work and about the “three-way merge.”

A simple branched repository#

This should be fairly routine by now. You’re going to set up a Git repository with two branches and some simple changes in them. Once that’s done, you’re going to try to cherry-pick a change from the abranch branch and apply it to the master branch.

1   mkdir lgthw_patch_and_apply
2   cd lgthw_patch_and_apply
3   git init
4   touch afile
5   git add afile
6   git commit -m 'afile added'
7   echo First change, on master >> afile
8   git commit -am 'First change, on master added'
9   git branch abranch
10  echo Second change, on master >> afile
11  git commit -am 'Second change, on master added'
12  git checkout abranch
13  echo First change, on abranch >> afile
14  git commit -am 'First change, on abranch added'
15  echo Second change, on abranch >> afile
16  echo New file, on abranch >> newfile
17  git add newfile
18  git commit -am 'Second change, on abranch added'
19  git tag abranchtag
20  git checkout master
Terminal 1
Terminal

Click to Connect...

Now that you’ve typed that in, use git log to look at the repository that you’ve created and all its changes. Make sure you look at it with the --all, --graph, and --decorate flags. Then check the changes at each commit with the --patch flag.

It’s important to get a grip on the repository that you are looking at before you try to perform surgery on it. This is what we’re about to do as we try and cherry-pick a change. Obviously, this repository is simplified but practicing this will help you as you move forward.

A simple cherry pick#

Before you type it in, think about what you expect the following cherry-pick command to do. You may be surprised by what happens, and the more surprised you are, the more likely you are to learn something useful!

First, take a look at the tag abranchtag to see what you’re going to cherry-pick:

21  git show abranchtag
Terminal 1
Terminal

Click to Connect...

You should see two changes: the addition of the “Second change, on abranch” line and a new file called newfile.

Now you’re going to cherry-pick the specific tag referenced by abranchtag. Write down what you think will happen, and then type in:

22  git cherry-pick abranchtag

Did that do what you expected?

Take a look at the afile file. Where did the First change, on abranch line come from? That wasn’t in the git show output!

You might be smarter than me, but I was not expecting to see that in there. I was expecting a conflict but not the First change, on abranch within it. I also expected to see the file newfile because that file was added on that commit.

In other words, I expected it to just try and apply the contents of git show and not introduce anything else to the mix.

Instead, it did this::

  • Tried to apply the change in the abranchtag commit
  • Saw that there was a conflict
  • Performed a three-way merge

Before showing you how to only apply the changes in the abranchtag commit as I originally intended, you will cover three-way merges first.

‘Falling back’ to a three-way merge#

Picture what the commit history looked like before you did the cherry-pick.

* 93c07a5 (tag: abranchtag, abranch) Second change, on abranch added
* 7fc9dcc First change, on abranch added
| * 2348f4c (HEAD -> master) Second change, on master added
|/
* 9c3f1af First change, on master added
* 9c01ac0 afile added

The HEAD is pointed at the master branch. The abranch branch is pointed at the same commit as the abranchtag tag.

Apply the cherry-pick the cherry-pick of the abranchtag commit (which has an ID of 93c07a5 here but will be different for you) to the master branch (which is at 2348f4c here).

What Git does is go to the first common ancestor (here, it is 9c3f1af First change, on master added) and sees what has changed between the abranchtag commit you want to apply and the master branch you are applying to. Conflicts are found. Git gives you all the changes on both branches from the first common ancestor and asks you to sort it out.

In other words, Git says: “I can’t apply that individual commit here without any conflicts, so I’m going to apply all the diffs between these two points, and let you figure out what’s going on.”

This is why it is called a “three-way merge.” The merge compares the changes between the source (abranchtag), the target (the master branch), and the first common ancestor (9c3f1af above).

Note: It only does this if there’s a conflict. If there is no conflict in the change, you cherry-pick, and then the three-way merge is not invoked. If you don’t believe me, then start over, but do not run the git commit -am 'Second change, on abranch added' line and see what happens.

Introduction: Cherry-Picking and Three-Way Merges
Generate and Apply Patch
Mark as Completed
Report an Issue