git cherry-pick seems to picks up two commits from a single hash

87 Views Asked by At

The below screenshot shows the result of running git cherry-pick <hash> while on branch master.

This operation is picking up two commits instead of a single commit. I don't understand why this is the case and wonder if this is a git bug. I am running version 2.30.

git cherry-pick a2a037f311 --no-commit

git cherry-pick

The next screenshot shows the commit log from the branch from which I am cherry-picking.

git log

Finally, here's a diff between two consecutive commits.

git diff 2bad... a2a0...

git diff

Here's some details about the branch being cherry-picked from.

It could be I've misunderstood something, but it seems to me the only thing that should be added from this single cherry-picking operation is the line

Include this change!

The only possible thought I have is that by picking a commit in the middle of a branch history, this for some reason creates a conflict with the previous commit. But that explanation doesn't seem to really make much sense given the details of the conflict shown here.

I would have expected:

  • No conflicts to occur from the cherry-pick
  • A single line Include this change! to be added to master branch

Why didn't that happen?


Mergetool:

mergetool

1

There are 1 best solutions below

2
joanis On

Thanks for the Mergetool output, that confirms what I expected.

To explain that view, the three top windows are LOCAL, BASE and REMOTE: LOCAL is what you're trying to cherry pick onto, BASE and before the commit you're cherry picking, and REMOTE is after, so the diff you're trying to apply to LOCAL is between BASE and REMOTE. The bottom window is the current state of the file, and the one you can edit into the resolved conflict.

Here we see that BASE and LOCAL have diverged: line 10 is in BASE but not in LOCAL. The cherry-picked commit says add a line "Including this changes" after a line "Don't include this change!", but Git is finding no such in LOCAL, and so it can't figure out where to add the line. That gets flagged as a conflict.

You might think "Well, it's obvious, just add the new line at the end." But that's only obvious to a human and it's not always the correct answer. If this was actual code, I would not be willing to bet that line 11 made sense without line 10. Git merges (and cherry picks and rebases, which are variants of merging) will not assume what the correct answer is, based on just a line-by-line diff, and so it flags a conflict to ask you to provide your judgement. You can then decide if line 11 without line 10 needs to have its syntax adjusted because line 10 is not there.