Advanced Git Commands: Cherry-Picking

TJ SimmonsMon, 10/15/2018 - 09:32

As developers, we first start out learning to use Git via simple repetition. We do the typical Git pull, Git push, Git fetch, and Git merge. At the start, we learn by doing, but after we move onto working on bigger projects—which means working on a team—we need to learn new, advanced Git commands.

One such advanced command is the Git cherry-pick. In this article, I'll explain the cherry-pick, when we typically use it, and when NOT to use it. I will also include pitfalls to be aware of when you run cherry-pick.

Cherry-Picking: An Intuitive Example

Imagine you're working on a team trying to produce a paper about the history and future evolution of the internet. So you split up the work among your team; everyone works on a different section, and at the end, everyone's work will be compiled into a single paper.

While you're writing your section, you feel you have some issues writing about Sir Tim Berners-Lee, the scientist who invented the World Wide Web. You have something, but you feel it could be better.

You mention the issue to a teammate, who says, "Oh I was writing about him as well for my section. Maybe you want to take a look."

So you look at your teammate's section. While his section is about the new direction of the internet, it does mention a fair bit about Tim Berners-Lee, enough for you to reuse. You don't want to copy everything your teammate wrote, so you cherry-pick some of the changes—the ones that will be most useful to you—and paste them into your own section. After that, you make more edits to your section to make the writing flow better.

That, in essence, is what it means to cherry-pick in Git. In other words, cherry-picking is when you want to take the contents of a single commit from another branch and copy-paste them to a destination branch as a brand new commit.

How to Use Cherry-Pick

The typical cherry-pick command is simply:

git cherry-pick <commit-hash>

Most documentation will simply leave you to that. As developers, we often perform a series of steps to achieve our objectives. Showing you an isolated cherry-pick command is the same as throwing you the manual and asking you to read it.

Recall the earlier analogy about writing a paper. Now let's use an imaginary case that's closer to the real-world software development process.

Step 1: Look for the Cherry

Let's say you are working on the branch rel_2.3 and you've got a bug on this branch. You tell your team about this, and your teammate Anna says, "Hey, I got the fix already, but it's in this branch dev."

This example should look like this:

advanced-git-commands-cherry-picking

 Fig 1: Before cherry-pick.

In the real world, nobody remembers the commit hash. Which is why Anna only tells you it's "somewhere in dev branch." So you check out dev branch and you go through the history:

git checkout dev

git reflog

Giving you this:

commit 83266e

Author: Anna <anna@fakeanna.com>
Date: Sat 1 Sep 2018 11:10

Commit message for H

commit 432a09

Author: Anna <anna@fakeanna.com>
Date: Sat 1 Sep 2018 10:45

Commit message for G

commit dadb52

Author: Anna <anna@fakeanna.com>
Date: Sat 1 Sep 2018 10:30

Commit message for F

The commit message for F sounds like it's the one you want. To be sure, you want to see the diffs of that particular commit, so you do:

git diff dadb52~ dadb52

You scroll through and you are satisfied that Anna is right. Now you've decided what to cherry-pick. Copy the commit hash to your clipboard; you will need it later.

Step 2: Switch to Destination Branch and Run the Command

This is the simple part of the process:

git checkout rel_2.3

git cherry-pick dadb52

Which means now you have:

advanced-git-commands-cherry-picking

 Fig 2: After cherry-pick, you have F

And you're done (assuming no conflicts, of course).

Think of cherry-pick as a highly targeted form of merge or rebase. So if you have conflicts after you cherry-pick, you need to resolve them. But before you run off, I want to highlight some recommendations for you so you have a complete understanding.

Recommendations for Using Cherry-Pick

There are three things you want to keep in mind when you use cherry-pick; if you do, your life working on a team will be much easier.

  1. Use a Standardized Commit Message

If you cherry-pick from a public branch, I strongly recommend you use:

git cherry-pick -x <commit-hash>

Chances are you may merge the branch you are working on back to the main branch and you want to avoid merge conflicts in the future. Therefore, it's ideal to use a standardized commit message. Personally, I recommend using this -x whenever you use cherry-pick. That is why I have it right at my conclusion where I summarize everything.

  1. Copy Over the Notes

Sometimes, the commit you cherry-pick has notes, and when you run cherry-pick, the notes don't get copied over. To be honest, this is rare because notes are rare. However, for completeness, I add this in.

git notes copy <from-commit-hash> <to-commit-hash>

  1. Cherry-Pick Multiple Commits Only When They're Linear

It can get tricky when the change you want to copy is spread across multiple commits. So using the Fig. 1 diagram, let's say we want to cherry-pick F, G, and H, and they are linear. The command will then be:

git cherry-pick F^..H

Note that the ^ means to include F. If it's not included, you will only pick G and H.

Many times, it might be easier to simply branch off and use merge and rebase if you want to pick multiple commits. So if you're going to use cherry-pick for multiple commits, do so with caution.

In Conclusion: The Recommended Sequence

Assuming we want to pick a specific commit from a different branch to our current branch, this is the recommended sequence of steps.

  1. Find the commit hash you want to cherry-pick.
  2. Go to your destination branch.
  1. git cherry-pick -x <commit-hash>
  1. Resolve conflicts if they occur.
  2. If there are notes in the original commit, copy them over.

git notes copy <original-commit-hash> <your-new-commit-hash>

In this article, I have explained the purpose of the cherry-pick command and under what conditions it is suitable. I have made three recommendations about what to watch out for when using cherry-pick. When you want to cherry-pick too many commits, I recommend starting a new merge-base branch and use merge and rebase instead of cherry-picking. Finally, for those who are impatient and want the "too long, didn't read" version, I wrote down a five-step process above. Hope this helps you better understand what cherry-pick is, and when and how to use it.