3 reasons I use the Git cherry-pick command | Opensource.com

3 reasons I use the Git cherry-pick command

Cherry-picking solves a lot of problems in Git repositories. Here are three ways to fix your mistakes with git cherry-pick.

Measuring and baking a cherry pie recipe
Image credits : 

Photo by Brooke Lark on Unsplash

x

Subscribe now

Get the highlights in your inbox every week.

Finding your way around a version control system can be tricky. It can be massively overwhelming for a newbie, but being well-versed with the terminology and the basics of a version control system like Git is one of the baby steps to start contributing to open source.

Being familiar with Git can also help you out of sticky situations in your open source journey. Git is powerful and makes you feel in control—there is not a single way in which you cannot revert to a working version.

Here is an example to help you understand the importance of cherry-picking. Suppose you have made several commits in a branch, but you realize it's the wrong branch! What do you do now? Either you repeat all your changes in the correct branch and make a fresh commit, or you merge the branch into the correct branch. Wait, the former is too tedious, and you may not want to do the latter. So, is there a way? Yes, Git's got you covered. Here is where cherry-picking comes into play. As the term suggests, you can use it to hand-pick a commit from one branch and transfer it into another branch.

There are various reasons to use cherry-picking. Here are three of them.

Avoid redundancy of efforts

There's no need to redo the same changes in a different branch when you can just copy the same commits to the other branch. Please note that cherry-picking commits will create a fresh commit with a new hash in the other branch, so please don't be confused if you see a different commit hash.

In case you are wondering what a commit hash is and how it is generated, here is a note to help you: A commit hash is a string generated using the SHA-1 algorithm. The SHA-1 algorithm takes an input and outputs a unique 40-character hash. If you are on a POSIX system, try running this in your terminal:

$ echo -n "commit" | openssl sha1

This outputs a unique 40-character hash, 4015b57a143aec5156fd1444a017a32137a3fd0f. This hash represents the string commit.

A SHA-1 hash generated by Git when you make a commit represents much more than just a single string. It represents:

sha1(
    meta data
        commit message
        committer
        commit date
        author
        authoring date
    Hash of the entire tree object
)

This explains why you get a unique commit hash for the slightest change you make to your code. Not even a single change goes unnoticed. This is because Git has integrity.

Undoing/restoring lost changes

Cherry-picking can be handy when you want to restore to a working version. When multiple developers are working on the same codebase, it is very likely for changes to get lost and the latest version to move to a stale or non-working version. That's where cherry-picking commits to the working version can be a savior.

How does it work?

Suppose there are two branches, feature1 and feature2, and you want to apply commits from feature1 to feature2.

On the feature1 branch, run a git log command, and copy the commit hash that you want to cherry-pick. You can see a series of commits resembling the code sample below. The alphanumeric code following "commit" is the commit hash that you need to copy. You may choose to copy the first six characters (966cf3 in this example) for the sake of convenience:

commit 966cf3d08b09a2da3f2f58c0818baa37184c9778 (HEAD -> master)
Author: manaswinidas <me@example.com>
Date:   Mon Mar 8 09:20:21 2021 +1300

   add instructions

Then switch to feature2 and run git cherry-pick on the hash you just got from the log:

$ git checkout feature2
$ git cherry-pick 966cf3.

If the branch doesn't exist, use git checkout -b feature2 to create it.

Here's a catch: You may encounter the situation below:

$ git cherry-pick 966cf3
On branch feature2
You are currently cherry-picking commit 966cf3d.

nothing to commit, working tree clean
The previous cherry-pick is now empty, possibly due to conflict resolution.
If you wish to commit it anyway, use:

   git commit --allow-empty

Otherwise, please use 'git reset'

Do not panic. Just run git commit --allow-empty as suggested:

$ git commit --allow-empty
[feature2 afb6fcb] add instructions
Date: Mon Mar 8 09:20:21 2021 +1300

This opens your default editor and allows you to edit the commit message. It's acceptable to save the existing message if you have nothing to add.

There you go; you did your first cherry-pick. As discussed above, if you run a git log on branch feature2, you will see a different commit hash. Here is an example:

commit afb6fcb87083c8f41089cad58deb97a5380cb2c2 (HEAD -> feature2)
Author: manaswinidas <me@example.com>
Date:   Mon Mar 8 09:20:21 2021 +1300
   add instructions

Don't be confused about the different commit hash. That just distinguishes between the commits in feature1 and feature2.

Cherry-pick multiple commits

But what if you want to cherry-pick multiple commits? You can use:

git cherry-pick <commit-hash1> <commit-hash2>... <commit-hashn>

Please note that you don't have to use the entire commit hash; you can use the first five or six characters.

Again, this is tedious. What if the commits you want to cherry-pick are a range of continuous commits? This approach is too much work. Don't worry; there's an easier way.

Assume that you have two branches:

  • feature1 includes commits you want to copy (from commitA (older) to commitB).
  • feature2 is the branch you want the commits to be transferred to from feature1.

Then:

  1. Enter git checkout <feature1>.
  2. Get the hashes of commitA and commitB.
  3. Enter git checkout <branchB>.
  4. Enter git cherry-pick <commitA>^..<commitB> (please note that this includes commitA and commitB).
  5. Should you encounter a merge conflict, solve it as usual and then type git cherry-pick --continue to resume the cherry-pick process.

Important cherry-pick options

Here are some useful options from the Git documentation that you can use with the cherry-pick command:

  • -e, --edit: With this option, git cherry-pick lets you edit the commit message prior to committing.
  • -s, --signoff: Add a "Signed-off-by" line at the end of the commit message. See the signoff option in git-commit(1) for more information.
  • -S[<keyid>], --gpg-sign[=<keyid>]: These are GPG-sign commits. The keyid argument is optional and defaults to the committer identity; if specified, it must be stuck to the option without a space.
  • --ff: If the current HEAD is the same as the parent of the cherry-picked commit, then a fast-forward to this commit will be performed.

Here are some other sequencer subcommands (apart from continue):

  • --quit: You can forget about the current operation in progress. This can be used to clear the sequencer state after a failed cherry-pick or revert.
  • --abort: Cancel the operation and return to the presequence state.

Here are some examples of cherry-picking:

  • git cherry-pick master: Applies the change introduced by the commit at the tip of the master branch and creates a new commit with this change
  • git cherry-pick master~4 master~2: Applies the changes introduced by the fifth and third-last commits pointed to by master and creates two new commits with these changes

Feeling overwhelmed? You needn't remember all the commands. You can always type git cherry-pick --help in your terminal to look at more options or help.

Digital creative of a browser on the internet

Submodules and subtrees help you manage child projects across multiple repositories.
Computer screen with files or windows open

These helpful tips will change the way you work with the popular version control system.

About the author

Manaswini Das - Manaswini Das is from Bhubaneswar and currently working with the Red Hat Middleware team in Bangalore, India. She is an active open-source user and contributor since 2017. She has participated both as a mentee and a mentor in various open-source programs including GCI, GSSoC, and RHOSC. She is an Outreachy alumnus and a Processing Foundation fellow. She loves sharing her knowledge at events and sketching.