Given that I have three commits in order,
c1
+ print("A")
c2
+ print("B")
c3
+ print("C")
Then I check out a new branch at c1.
git checkout -b br c1
Then I cherry-pick c3.
git cherry-pick c3.
I want that the file has
print("A")
print("C")
I just pick c3 and c3. Just add the line print("C").
But the fact is I got conflicts and the result is
print("A")
++<<<<<<< HEAD
++=======
+ print("B")
+ print("C")
++>>>>>>> f1383aa... C
I also even tried:
git diff C^1 .. C > 1.patch
git apply 1.patch
I got
cd ~/g/demo
git apply 1.patch
Output:
error: patch failed: 1.py:1
error: 1.py: patch does not apply
Cherry-picking is essentially copying (the effects of) a commit. You can think of it the way you obviously are—i.e., as diff the to-be-picked commit and its parent, then apply that diff to the current commit. However, it's more powerful than a mere diff-and-apply, because it has access to Git's full merge mechanism.
What this means is that git cherry-pick
is really a full blown git merge
internally, with the two commits being merged being your current commit—your HEAD
—and the commit you are cherry-picking. The merge base for this operation is the parent of the commit you are cherry-picking.
The reason to do this is that, as you have seen, you can get a merge conflict if both your HEAD
commit and the commit you are cherry-picking have changed "the same" lines. In this case, your HEAD
commit added the line print("A")
, probably at the end of the file, but in any case right before some other line. Meanwhile, the commit you are telling Git to cherry-pick—commit c3—adds the line print("C")
at the same place (at the end of the file, or before the same existing line). Git does not know where to place the added print
, so it declares a conflict and makes you choose the correct answer.
The solution is simple enough: open the conflicted file in your editor and adjust it to contain the correct resolution of the conflict, then write this out and use git add
on the file so that you can run git cherry-pick --continue
to finish up the cherry-picking process. Or, if you prefer, use a merge tool to obtain all three input files (base, "ours" or HEAD
, and "theirs" or c3's version) and resolve the conflict that way.
For more about cherry-pick, see What does cherry-picking a commit with git mean?