Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git cherry-pick causes merge conflict while merging does not

I am trying to learn how to use git cherry pick, I read the manual pages that git returns by doing git cherry-pick --help but that did not seem to help. I will try and explain the problem below. I have two branches master and other.

On branch master The commit history is

0x2 Second commit from master branch
0x1 Initial commit

And the only file in the repository that I am tracking readme has the following contents

Some text

On branch other The commit history is

0x5 CHECKPOINT, going to cherry-pick onto master
0x4 second commit from branch other
0x3 first commit from other branch:
0x2 Second commit from master branch
0x1 Initial commit

And the contents of the readme file are

Some text.

Adding some text from other branch.  Adding some more text.

Going to cherry-pick this commit.

The working directory is clean on both branches with no untracked changes. From this point on when I switch to the master branch and merge with git merge other the merge happens gracefully with no merge conflicts. But when I try git cherry-pick 0x5 there is a merge conflict, I get the following output from git

error: could not apply 0x5... CHECKPOINT, going to cherry-pick onto master
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

And the readme file has the following contents

<<<<<<< HEAD
Some text
=======
Some text.

Adding some text from other branch.  Adding some more text.

Going to cherry-pick this commit.
>>>>>>> 0x5... CHECKPOINT, going to cherry-pick onto master

Why is there this merge conflict? I am trying to understand why it occurs. Shouldn't cherry-picking be the same as trying to make all the edits made on the commit that is to be cherry-picked yourself and then commiting that change onto the branch (master in this case)?

Also when exactly is there a merge conflict in git? I seem to get them at weird times. Is this implementation dependent (for example dependent on the algorithm used to merge)?

Thank you!

like image 925
Curious Avatar asked May 15 '16 11:05

Curious


People also ask

How do you resolve a merge conflict in cherry-pick?

Resolve the conflicts. Resume: Depending on the command that was executed (e.g. rebase, merge, cherry-pick), you will usually need to add the files and call something like rebase --continue or cherry-pick --continue.

Is it possible to get merge conflict during git cherry-pick?

Yes, at least with the standard git setup. You cannot cherry-pick while there are conflicts. Furthermore, in general conflicts get harder to resolve the more you have, so it's generally better to resolve them one by one. That said, you can cherry-pick multiple commits at once, which would do what you are asking for.

What happens when you cherry-pick a merge commit?

Also consider that when you cherry-pick a merge commit, it collapses all the changes made in the parent you didn't specify to -m into that one commit.

What is the difference between cherry-pick and merge?

With the cherry-pick command, Git lets you incorporate selected individual commits from any branch into your current Git HEAD branch. When performing a git merge or git rebase , all the commits from a branch are combined. The cherry-pick command allows you to select individual commits for integration.


1 Answers

I just tested that scenario, after reading:

  • "Why does cherry-pick always result in a merge conflict?"
  • "Demystifying Git: 3 Concepts to Do Everything with Git"

If the modification to the first line (Some text. instead of Some text) was done immediately after 0x2, as in 0x3, then git cherry-pick 0x3 works without conflict.

But if that same change is done a few commits later, the git cherry-pick won't generate a patch compatible with the content of 0x2.

There is no notion of "common ancestor" here (as incorrectly stated here): only of "patch".

A git cherry-pick, even if it uses merging strategies, is not a git merge.

  • A git merge will look for a common ancestor (going back in the history of commits of 0x5, to find a common commit with 0x2: here 0x2 itself)
  • A git cherry-pick only creates a patch by doing a unified diff between two commits (by default, the commit you mention and its immediate parent 0x4)

The point is: that patch won't be able to be applied on top of 0x2.

Try if for yourself: a git cherry-pick 0x5 is like doing a git diff -p 0x4..0x5.
You will see in that patch lines which are not part of 0x2, and reflect changes coming from 0x3 or 0x4.

Such a patch cannot be applied on 0x2, as it is based on a content which does not exist for 0x2.

I have created a test repo in which I made from master two modifications.

  • Adding some text from other branch (no modification to the first line)
  • Then a second commit modifying the first line.

Here what my patch looks like:

C:\Users\vonc\prog\git\tests\cp>git diff -p dev~..dev
diff --git a/f b/f
index 2b6dd7b..1c4bb79 100644
--- a/f
+++ b/f
@@ -1,4 +1,4 @@
-"Some text"
+"Some text."^M

 Adding some text from other branch.  Adding some more text.

I cannot apply (cherry-pick) that commit onto 0x2, as 0x2 has no line "Adding some text from other branch" yet. It only has one line "Some text".

That is why git reports a conflict: the content has diverged, and that patch is supposed to change line 1 on top of a file including "Adding some text from other branch", which 0x2 does not have.

This differs from a git merge of course, as a git merge will look for a common ancestor (here 0x2) and reports all modifications since 0x2 onto 0x2 without any issue.


The OP Curious asked in the comments

will cherry-pick likely always generate a merge conflict in large projects with every single file that was changed?

Farid answers:

Yes in slightly big projects cherry picking will be pain in the ass for the files where cherry-picked commit is not direct "child" of the commit in the branch you are trying to cherry-pick onto.

like image 152
VonC Avatar answered Oct 03 '22 20:10

VonC