0

I have the following situation in my commit history:

A1-...-A2
         \
          B1-B2-...-B3----------B4-B5
                      \        /
                       C1-C2-C3

I then did (after git checkout A2 and a clean git status) git cherry-pick --no-commit C2..B5. Now, C2 introduced an important line in file1.txt, say

file1.txt
-line x
+line x with new part

and "line x with new part" exists in all commits C2 to B5. But after the cherry-pick, the change does not appear and file1.txt still looks like

...
line x
...

where I expected a line "line x with new part". I thought, I don't understand the changes and did

git diff HEAD C2 file1.txt
file1.txt
-line x
+line x with new part

which shows the change as expected. I also checked git diff HEAD C3 file1.txt, git diff HEAD B4 file1.txt and git diff HEAD B5 file1.txt with the same result.

git rev-parse HEAD results in A2 as intended and git status says "On branch A, Your branch is up to date with 'origin/A'. nothing to commit, working tree clean".

What do I miss? Any ideas?

References:
How to cherry pick a range of commits and merge into another branch,
How to merge a specific commit in Git and
Pull all commits from a branch, push specified commits to another (I hope, it is not an issue with a comment from the answer "...Likewise, cherry picking a commit from one branch to another basically involves generating a patch, then applying it, thus losing history that way as well." from the answer.).

Edit @eftshift0: After git cherry-pick --no-commit C1..B5 it looks correct at a first glance:
The Diff shows

<<<<<<< HEAD
line x                         # current status of A2
||||||| parent of C2...
line x                         # common ancestors of C1 and A2
=======
line x with new part           # from merge (new stuff)
>>>>>>> C2...

From the docs:

git-cherry-pick - Apply the changes introduced by some existing commits SYNOPSIS

DESCRIPTION Given one or more existing commits, apply the change each one introduces, recording a new commit for each. This requires your working tree to be clean (no modifications from the HEAD commit).

Christoph
  • 5,963
  • 3
  • 31
  • 73

1 Answers1

2

Because you are saying C2..B5, the change from C2 is not considered. try C1..B2.

eftshift0
  • 16,836
  • 2
  • 23
  • 36
  • Could you explain, why you need one more commit? If you look at any combination A2-X (X=C2, ...) the change is displayed in the diff. Does cherry-pick relay on something else? I made a dummy example and it worked as expected (I thought). – Christoph Jan 13 '20 at 16:31
  • See my edit... It seems, you are right, but I am quite confused. As the code is used "in production" I would like to understand, why you are right. Thanks! – Christoph Jan 13 '20 at 16:42
  • Explanation is pretty straight forward. When you use cherry-pick with a range of revisions, the _first_ revision that is just the starting point and it is not applied on. The revisions following it are the ones that will be applied on top of where you are working... so if you wanted to see the change that is coming from C2 to be applied on where you are working, you have to specify C1 as the starting point... and what do you mean I _seem_ to be right? I **am** right. :-D – eftshift0 Jan 13 '20 at 16:52
  • Ok :-) I read the documentation and I still would not get your point from the docs. Are the docs clear to you with respect to this question? – Christoph Jan 13 '20 at 17:00
  • you mean, do I find an inconsistency there? I might take a look and send over a patch if I think wording might be improved. – eftshift0 Jan 13 '20 at 17:04
  • Yes: to me, the doc is not clear, but perhaps this is because I am not a native speaker... – Christoph Jan 13 '20 at 17:11
  • See e.g. here https://stackoverflow.com/a/30218784/5784831: ...The command git cherry-pick commit applies the changes introduced by the named commit on the current branch. – Christoph Jan 13 '20 at 17:33
  • 1
    @Christoph: Git consistently uses ranges this way. It's annoying for the cherry-pick case in particular when you're using it the way you are, but if cherry-pick acted differently, that would be tricky to explain and model, because ranges don't mean what they look like in the first place. That is, `X..Y` does not mean "start at X and work forward to Y". It actually means "start at Y and work backwards all the way through time. Then, start at X and work backwards all the way through time. Take the *second* group of commits away from the *first* one." – torek Jan 13 '20 at 22:50
  • Git actually *has* to do this internally, because its internal working *are* all backwards. But then, rather than make user friendly interfaces, Git just exposes these inner workings directly to you. :-) – torek Jan 13 '20 at 22:51
  • @torek One change which was introduced in C3 (and not reverted or changed afterwards) is also missing after `git cherry-pick --no-commit C1..B5`. Does that make sense to you? `B4` was a `-no-ff` commit. By the way: When I see, what git expects the user to know, I consider my question as valuable ;-) – Christoph Jan 28 '20 at 13:44
  • The range expression `C1..B5` should include C3, and cherry-picking C3 will use C2 as a merge base and C3 as the other commit. The result will follow the usual merge rules. Note, however, that since B4 is a merge commit, it cannot be cherry-picked as part of a range operation: cherry-picking B4 requires specifying *which parent* to use as it has two, while the others require *not specifying which parent to use* as they have only one. – torek Jan 28 '20 at 15:19