I saw that there is a connection between rebase
and cherry-pick
a range of commits.
I have failed to find any article/toturial which explain what exactly happands when one try to cherry-pick
multiple commits.
Some questions (which I can think of) are:
CHERRY_PICK_HEAD
ref is?git cherry-pick 2^..4
, what is the sequence of actions git does and exactly between which commits git use diff
?git cherry-pick 1..8
, what git will do?Cherry picking n
commits is the same as cherry picking one of them after the other (with distinct git calls). No branching or whatever else is involved, simply new commits created for you on the current branch.
The help page https://www.git-scm.com/docs/git-cherry-pick.html says:
Given one or more existing commits, apply the change each one introduces, recording a new commit for each.
Let's pick that statement apart:
the change
This is what sometimes is also called "the diff". It is what git diff HEAD somecommit
would output. Sometimes it is also called a "patch" (in fact, that same output from git diff
could be applied with the usual patch
utility - and of course with git apply
but that's not the point here).
So, the "change" is something that instructs a tool like git
or patch
how to modify a text file to end up with a new, changed text file.
You could create a similar textual representation of the differences between two files by running the standard diff
utility on two files. In fact, that is what git
does with a cherry-pick, internally (with its own diff implementation, of course); i.e. this is only a 2-way diff, not a 3-way diff like in the git merge
operation.
each one introduces
When you have this state:
...----+----+----...
abc def
Then the git cherry-pick def
change is the 2-way diff between commits abc
and def
(for all the files which differ, of course, on a file-by-file basis), because this is what def
"introduces".
apply the change
This means to take HEAD
and "the change" (i.e., the diff, the patch, etc.) and create a new set of text files. You can treat this, in principle as a 2-way merge (just like the patch
utility would do) except when it isn't, i.e. if the context information in the diff
output does not match what's in HEAD
right now. In that case, git cheats to find a common ancestor to be able to do a 3-way merge, and you can read up the gory details in What are the three files in a 3-way merge for interactive rebasing using git and meld? . But it is still, from the user's point of view, not really comparable to a git merge
insofar as structurally it will end up with a single-parent commit, not a 2-parent commit like git merge
.
recording a new commit
git
applies the changes to the index and to the working directory, and commits. Unless the 2-way merge and the 3-way merge did not work out without a conflict, in which case, straight from the help page with some comments of mine:
def
in my picture above.]And finally, the rest of the sentence:
Given one or more existing commits, apply ... recording a new commit for each.
If you give it more than one commits, maybe explicitly as in git cherry-pick sha1 sha2 sha3...
or implicitly git cherry-pick sha1..sha2
, then the above just runs in a simple loop, stopping after the last pick, or when there occurs a merge conflict.
What CHERRY_PICK_HEAD ref is?
2. The CHERRY_PICK_HEAD ref is set to point at the commit that introduced the change that is difficult to apply.
If it tries to pick commit def
, and a merge conflict occurs, then CHERRY_PICK_HEAD
will point at def
.
By running git cherry-pick 2^..4, what is the sequence of actions git does and exactly between which commits git use diff?
As described above:
git cherry-pick --continue
.By running git cherry-pick 1..8, what git will do?
The same, but this time it will pick commit 2, 3, 4, 8.
(The fact that the "first" commit in the range is not picked is the usual behaviour, for example git log 2^..4
or git log 1..8
would output the same commits - in fact the same that would be picked. This is described in the cherry-pick help page under <commits>
including links to how git walks revisions, for all the details. This is not a property of git cherry-pick
but of how these ..
ranges work.)