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):
17 Answers
Git 1.7.2 introduced the ability to cherry pick a range of commits. From the release notes:
git cherry-picklearned to pick a range of commits (e.g.cherry-pick A..Bandcherry-pick --stdin), so didgit revert; these do not support the nicer sequencing controlrebase [-i]has, though.
To cherry-pick all the commits from commit A to commit B (where A is older than B), run:
git cherry-pick A^..B
If you want to ignore A itself, run:
git cherry-pick A..B
Notes from comments:
Ashould be older thanB, orAshould be from another branch.- On Windows, it should be
A^^..Bas the caret needs to be escaped, or it should be"A^..B"(double quotes). - In
zshshell, it should be'A^..B'(single quotes) as the caret is a special character. - For an exposition, see the answer by Gabriel Staples.
(Credits to damian, J. B. Rainsberger, sschaef, Neptilo, Pete and TMin in the comments.)
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
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
Or the requested one-liner:
git rebase --onto a b f
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 ...
To summarize the commands in text form:
- Open gitk as a independent process using the command:
gitk --all &. - Run
git rebase --onto a b f. - Press F5 in gitk. Nothing changes. But no
HEADis marked. - Run
git branch selection - Press F5 in gitk. The new branch with its commits appears.
This should clarify things:
- Commit
ais the new root destination of the group. - Commit
bis the commit before the first commit of the group (exclusive). - Commit
fis 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.
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
How to cherry-pick a single commit, multiple commits, or a range of commits
...onto your currently-checked-out branch: