[git] How to cherry-pick multiple commits

I have two branches. Commit a is the head of one, while the other has b, c, d, e and f on top of a. I want to move c, d, e and f to first branch without commit b. Using cherry pick it is easy: checkout first branch cherry-pick one by one c to f and rebase second branch onto first. But is there any way to cherry-pick all c-f in one command?

Here is a visual description of the scenario (thanks JJD):

enter image description here

This question is related to git git-rebase cherry-pick

The answer is


git rev-list --reverse b..f | xargs -n 1 git cherry-pick

If you have selective revisions to merge, say A, C, F, J from A,B,C,D,E,F,G,H,I,J commits, simply use below command:

git cherry-pick A C F J


Here's a script that will allow you to cherry-pick multiple commits in a row simply by telling the script which source and target branches for the cherry picks and the number of commits:

https://gist.github.com/nickboldt/99ac1dc4eb4c9ff003a1effef2eb2d81

To cherry-pick from your branch to master (uses the current branch as source):

./gcpl.sh -m

To cherry-pick the latest 5 commits from your 6.19.x branch to master:

./gcpl.sh -c 5 -s 6.19.x -t master

Or the requested one-liner:

git rebase --onto a b f

Actually, the simplest way to do it could be to:

  1. record the merge-base between the two branches: MERGE_BASE=$(git merge-base branch-a branch-b)
  2. fast-forward or rebase the older branch onto the newer branch
  3. rebase the resulting branch onto itself, starting at the merge base from step 1, and manually remove commits that are not desired:

    git rebase ${SAVED_MERGE_BASE} -i
    

    Alternatively, if there are only a few new commits, skip step 1, and simply use

    git rebase HEAD^^^^^^^ -i
    

    in the first step, using enough ^ to move past the merge-base.

You will see something like this in the interactive rebase:

pick 3139276 commit a
pick c1b421d commit b
pick 7204ee5 commit c
pick 6ae9419 commit d
pick 0152077 commit e
pick 2656623 commit f

Then remove lines b (and any others you want)


Another variant worth mentioning is that if you want the last n commits from a branch, the ~ syntax can be useful:

git cherry-pick some-branch~4..some-branch

In this case, the above command would pick the last 4 commits from a branch called some-branch (though you could also use a commit hash in place of a branch name)


git format-patch --full-index --binary --stdout range... | git am -3

You can use a serial combination of git rebase and git branch to apply a group of commits onto another branch. As already posted by wolfc the first command actually copies the commits. However, the change is not visible until you add a branch name to the top most commit of the group.

Please open the picture in a new tab ...

Workflow

To summarize the commands in text form:

  1. Open gitk as a independent process using the command: gitk --all &.
  2. Run git rebase --onto a b f.
  3. Press F5 in gitk. Nothing changes. But no HEAD is marked.
  4. Run git branch selection
  5. Press F5 in gitk. The new branch with its commits appears.

This should clarify things:

  • Commit a is the new root destination of the group.
  • Commit b is the commit before the first commit of the group (exclusive).
  • Commit f is the last commit of the group (inclusive).

Afterwards, you could use git checkout feature && git reset --hard b to delete the commits c till f from the feature branch.

In addition to this answer, I wrote a blog post which describes the commands in another scenario which should help to generally use it.


The simplest way to do this is with the onto option to rebase. Suppose that the branch which current finishes at a is called mybranch and this is the branch that you want to move c-f onto.

# checkout mybranch
git checkout mybranch

# reset it to f (currently includes a)
git reset --hard f

# rebase every commit after b and transplant it onto a
git rebase --onto a b

To apply J. B. Rainsberger and sschaef's comments to specifically answer the question... To use a cherry-pick range on this example:

git checkout a
git cherry-pick b..f

or

git checkout a
git cherry-pick c^..f

To cherry pick from a commit id up to the tip of the branch, you can use:

git cherry-pick commit_id^..branch_name


Examples related to git

Does the target directory for a git clone have to match the repo name? Git fatal: protocol 'https' is not supported Git is not working after macOS Update (xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools) git clone: Authentication failed for <URL> destination path already exists and is not an empty directory SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443 GitLab remote: HTTP Basic: Access denied and fatal Authentication How can I switch to another branch in git? VS 2017 Git Local Commit DB.lock error on every commit How to remove an unpushed outgoing commit in Visual Studio?

Examples related to git-rebase

rebase in progress. Cannot commit. How to proceed or stop (abort)? git remove merge commit from history Choose Git merge strategy for specific files ("ours", "mine", "theirs") What's the difference between 'git merge' and 'git rebase'? Your branch is ahead of 'origin/master' by 3 commits Rebase feature branch onto another feature branch git rebase merge conflict Remove folder and its contents from git/GitHub's history How to get "their" changes in the middle of conflicting Git rebase? How to rebase local branch onto remote master

Examples related to cherry-pick

Git Cherry-Pick and Conflicts What does cherry-picking a commit with Git mean? git cherry-pick says "...38c74d is a merge but no -m option was given" How to git-cherry-pick only changes to certain files? How to cherry pick from 1 branch to another Is it possible to cherry-pick a commit from another git repository? Remove specific commit How to cherry-pick multiple commits Git Cherry-pick vs Merge Workflow