When to use git cherry-pick & how 🍒
Tags: github, git, intermediate
Published: 2021-09-15 11:16:27

## Table of Contents
* [Intro](#intro)
* [But why?](#but-why)
* [Let's see how](#lets-see-how)
    * [Setup](#the-setup)
    * [Simulating the error](#the-error)
    * [Cherry picking 🍒](#cherry-pick)
* [Keep this in mind](#keep-this-in-mind)


## Intro <a name="intro"></a> 

Without much ado, let's get right into it...

So, the [official git docs](https://git-scm.com/docs) describe `cherry-pick` as the following:
> Given one or more existing commits, apply the change each one introduces, recording a new commit for each.

So let us see what that means exactly...

## But why? <a name="but-why"></a>

OK, picture this: 
- You're working on a project and you're inside a local git repository. 
- You have been working on an awesome feature on a separate branch.
- You just added some more code and committed.

But wait. You had to commit to the feature branch, but you committed to master :scream:

What do you do in this case? Do you copy your code and paste it in the right branch and then commit again? 

Now this is exactly why you need `git cherry-pick`. **It allows you to "cherry-pick" commits from one branch and put them elsewhere (on another branch).**

## Let's see how <a name="lets-see-how"></a>

Now that you have an understanding of why you might need it, let's see how you can use it with a small example.

### Setup <a name="the-setup"></a>

First, I'll `cd` to my Desktop and create a brand new folder called "learning" with this command:
```bash
cd Desktop && mkdir learning
```

Now let's `cd` into our new directory:
```bash
cd learning
```
Now let's initialize a new git repository in this new folder with the command `git init`:
![git init image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ny7c13s3v0a87mydbfwj.png)

OK, our git repository is ready. Let's create a new file now and commit the changes...
![create commit in git](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cyfwpxd49gbsnnstn05g.png)

Now, let's create a new branch and add one commit there too:
![new branch commit](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m9n5nmlleiecbxq94vz4.png)

OK, now let's quickly check our git logs to see the commits we have currently. We'll use this command for each branch:
```bash
git log --oneline --graph
```
> :information_source: **:** `-oneline` will give us all info for each commit in a single line and `--graph` will make it look nice in a tree like format.

#### Log for the `master` branch
![master branch log](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6iz7z2u3clqbk7i9vxkl.png)
 
#### Log for the `some-awesome-feature` branch
![some new feature log](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0gtnbxmokknegwgyz2gl.png)

Let's simulate the error now :yum:

### Simulating the error <a name="the-error"></a>

Now to simulate the error, we will make a commit to the `master` branch that should have been made to the `some-awesome-feature` branch.

Let's do that:
![wrong commit](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/31renaphmcxa05fpq54g.png)

Good job! :partying_face: 
Now onto cherry-picking 🍒

### Cherry Picking 🍒 <a name="cherry-pick"></a>

First, checking the wrong branch (the `master` branch in this case), we see the commit that we want to pick and *copy* to the right branch.

#### Log for the `master` branch
![master branch log](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8iq6b1xvmutx92nwuog2.png)

#### Log for the `some-awesome-feature` branch
![some new feature log](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0gtnbxmokknegwgyz2gl.png)

Now, first to copy the commit over from `master` to the right branch, we need the commit hash of that commit.

If you look at the wrong branch carefully (the `master` branch in our case), the commit hash is `67d2e2f`

This is important because we need to tell cherry-pick which commit has to be copied.

Now, to cherry-pick, we always `git checkout` to the right branch first. Let's do that with:
```bash
git checkout some-awesome-feature
```

A quick `git log` on this branch:
![git log on correct branch](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ij4ydy9hr0jthdf4b50w.png)
 
We can see that the commit we want here, isn't there.

Let's use the magic :sparkles: of `cherry-pick`, the one command you have been waiting for!

On the branch that we want the commit to be on, we'll run this:
```bash
git cherry-pick <commit_hash_of_the_commit_you_want_here>
```
> As you saw earlier, the hash of the commit we want is `67d2e2f` so we'll use that.

![after cherry-pick](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pklw1nq8qi1s42iw95ay.png)
 
Boom! :boom:. We're done! Let's check?

Let's check the git log for this branch again:
![final log after cherry-pick](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2rhxjwuzp9c81pdlpt37.png)

Whoaa :confetti_ball: 

However, notice that the commit has a different hash here :hushed:. That's what we'll discuss in the final part of this post...

## Keep this in mind <a name="keep-this-in-mind"></a>

For the final time, let's check the commit logs for both the branches

#### Log for the `master` branch
![master branch log](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/stucxvl99scs1ogr80e2.png)

#### Log for the `some-awesome-feature` branch
![other branch log](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d19sll625uefuvu2fqm4.png)

#### 1.
=======
You can see that the commit we cherry-picked has not been moved from our wrong branch (the `master` branch in our case), but it has been copied.

This is what is called a "replay". Git did not move your commit but instead replayed the changes on the right branch, which is exactly why the commit has a different hash than the original one.

The original commit will always remain where it has been and it is your responsibility to delete it from there (using something like `git reset`)


#### 2.
=======
You saw how the hash of the copied commit is different form the original, and this is why you should avoid using these commands if you've already pushed the changes to a remote repository (say GitHub for instance), because if you do, other collaborators on the project would have a different history than yours and this could mess a lot of things up.

-----------

Aaaand that's it from me! I thank you so much for reading through. You are awesome! :partying_face:

If you loved it, you can show some love on [Twitter](https://twitter.com/androidanyl) and / or leave your beautiful comments below.

Corrections & Suggestions welcome.