The cherry-pick command in git allows you to copy commits from one branch to another, one commit at a time. In order to copy more than one commit at once, you need a different approach.

Cherry-picking a single commit

Say we have the following repository composed of three branches (master, feature1 and stable):

$ git tree --all  
* d9484311 (HEAD, master) Delete test file  
* 4d4a0da8 Add a test file  
| * 5753515c (stable) Add a license  
| * 4b95278e Add readme file  
|/  
| * a37658bd (feature1) Add fourth file  
| * a7785c10 Add lines to 3rd file  
| * 7f545188 Add third file  
| * 2bca593b Add line to second file  
| * 0c13e436 Add second file  
|/  
* d3199755 Add a line  
* b58d925c Initial commit

The "git tree" command is an alias I defined in my ~/.gitconfig:

[alias]  
tree = log --oneline --decorate --graph

To copy the license file (commit 5753515c) to the master branch then we simply need to run:

$ git checkout master  
$ git cherry-pick 5753515c  
Finished one cherry-pick.  
[master 08ff7d4] Add a license  
1 files changed, 676 insertions(+), 0 deletions(-)  
create mode 100644 COPYING

and the repository now looks like this:

$ git tree --all  
* 08ff7d4a4 (HEAD, master) Add a license  
* d94843113 Delete test file  
* 4d4a0da88 Add a test file  
| * 5753515c (stable) Add a license  
| * 4b95278e Add readme file  
|/  
| * a37658bd (feature1) Add fourth file  
| * a7785c10 Add lines to 3rd file  
| * 7f545188 Add third file  
| * 2bca593b Add line to second file  
| * 0c13e436 Add second file  
|/  
* d3199755 Add a line  
* b58d925c Initial commit

Cherry-picking a range of commits

In order to only take the third file (commits a7785c10 and 7f545188) from the feature1 branch and add it to the stable branch, I could cherry-pick each commit separately, but there is a faster way if you need to cherry-pick a large range of commits.

First of all, let's create a new branch which ends on the last commit we want to cherry-pick:

$ git branch tempbranch a7785c10  
$ git tree --all  
* 08ff7d4a (HEAD, master) Add a license  
* d9484311 Delete test file  
* 4d4a0da8 Add a test file  
| * 5753515c (stable) Add a license  
| * 4b95278e Add readme file  
|/  
| * a37658bd (feature1) Add fourth file  
| * a7785c10 (tempbranch) Add lines to 3rd file  
| * 7f545188 Add third file  
| * 2bca593b Add line to second file  
| * 0c13e436 Add second file  
|/  
* d3199755 Add a line  
* b58d925c Initial commit

Now we'll rebase that temporary branch on top of the stable branch:

$ git rebase --onto stable 7f545188^ tempbranch  
First, rewinding head to replay your work on top of it...  
Applying: Add third file  
Applying: Add lines to 3rd file  
$ git tree --all  
* ec488677 (HEAD, tempbranch) Add lines to 3rd file  
* a85e5281 Add third file  
* 5753515c (stable) Add a license  
* 4b95278e Add readme file  
| * 08ff7d4a (master) Add a license  
| * d9484311 Delete test file  
| * 4d4a0da8 Add a test file  
|/  
| * a37658bd (feature1) Add fourth file  
| * a7785c10 Add lines to 3rd file  
| * 7f545188 Add third file  
| * 2bca593b Add line to second file  
| * 0c13e436 Add second file  
|/  
* d3199755 Add a line  
* b58d925c Initial commit

All that's left to do is to make stable point to the top commit of tempbranch and delete the old branch:

$ git checkout stable  
Switched to branch 'stable'  
$ git reset --hard tempbranch  
HEAD is now at ec48867 Add lines to 3rd file  
$ git tree --all  
* ec488677 (HEAD, tempbranch, stable) Add lines to 3rd file  
* a85e5281 Add third file  
* 5753515c Add a license  
* 4b95278e Add readme file  
| * 08ff7d4a (master) Add a license  
| * d9484311 Delete test file  
| * 4d4a0da8 Add a test file  
|/  
| * a37658bd (feature1) Add fourth file  
| * a7785c10 Add lines to 3rd file  
| * 7f545188 Add third file  
| * 2bca593b Add line to second file  
| * 0c13e436 Add second file  
|/  
* d3199755 Add a line  
* b58d925c Initial commit  
$ git branch -d tempbranch  
Deleted branch tempbranch (was ec48867).

It would be nice to be able to do it without having to use a temporary branch, but it still beats cherry-picking everything manually.

Another approach

Another way to achieve this is to use the format-patch command to output patches for the commits you are interested in copying to another branch and then using the am command to apply them all to the target branch:

$ git format-patch 7f545188^..a7785c10  
0001-Add-third-file.patch  
0002-Add-lines-to-3rd-file.patch  
$ git am *.patch

Update: looking forward to git 1.7.2

According to a few people who were nice to point this out in a comment, version 1.7.2 of git, which is going to be released soon, will have support for this in cherry-pick:

git cherry-pick 7f545188^..a7785c10

You have a mistake in your alias that got me confused at first: It's not "--pretty=oneline" but it's "--oneline" instead (or "--pretty=oneline --abbrev-commit"). Otherwise you'll get the full commit IDs which are rather unhandy.

Thanks for this helpful article, and even more for the useful alias. :)

Enjoy!

Comment by rhonda
Are you looking for the "-i" option?
Comment by Simon

And with git v1.7.2 you'll be able to use:

git cherry-pick 7f545188^..a7785c10

:-)

Comment by Björn Steinbrink
Now Simon already talked about interactive rebase, but another point: there's no need to rebase stable --hardly to the other branch. In fact, as the target was rebased a "git merge" will be a fast-forward, so can be done without generating a merge commit.
Comment by Philipp Kern

For any older git:

git rev-list ^f545188 master --reverse | git cherry-pick --stdin

Comment by Motiejus Jakštys