git cherry-pick weird issue, sometimes conflicts but sometimes not

隐身守侯 提交于 2021-02-08 10:30:49

问题


Let's say we have below history:

     master->m2   s2<-second
             |     |
             m1   s1
               \ /
                a0

so a0 is the initial commit that has a text file called letter.txt that contain a letter a, each commit on the master branch append the next alphabet, so the letter.txt in m1 contains ab and m2 contains abc, then I checkout the second branch and on I add a new file let's say bugfixcode.cs, so s1 and s2 are all in regards to add/modify bugfixcode.cs, then I switch back to master, and find I want to cherry-pick some commit from second branch, here is something weird:

Q1. if I cherry-pick s2, then it will be a conflict, but if I cherry-pick s1, then no conflict. For the conflict when cherry-picking s2, I think it is because the content of letter.txt on the second branch is still a, but the file on m2 has abc, but isn't that the same fact on s1? why there is no conflict on s1

Q2. For the conflict when cherry-picking s2, why there is no conflict marker like <<<<<<< HEAD in letter.txt? if there is no conflict marker , then there is no conflicts, isn't it?


回答1:


This has nothing to do with letter.txt. It's about bugfixcode.cs.

What's a cherry-pick? It is a merge performed as if the parent of the target commit (the commit named at the end of the cherry-pick command) were the ancestor of both commits (the target commit and the commit we are cherry-picking onto, i.e. HEAD).

To put it another way, it is a replay (onto HEAD) of the diff (the patch) that gets you from the target commit's parent to the target commit.

So you've got this:

--- A has no file x
\
 \--- B creates file x --- C modifies file x

So now you try to cherry-pick C onto A. That means: replay the B-to-C diff on top of A. You are saying: "Please do to me, A, what you did to B in order to get C."

Well, what did you do to B in order to get C? What is the difference between B and C? It's the modification of file x. But in A there is no file x at all! So what on earth does that mean? How can we, starting with A, modify a file that isn't even there? Git has no idea, so it throws up its hands.

(The same problem doesn't exist if you cherry-pick B onto A, because it is obvious what the diff is there: create the file.)

To see this in a controlled way, just play out the scenario. Keep your eye on the file that I call file2:

git init
echo "howdy" > file
git add .
git commit -m "start"

git branch mybranch
git checkout mybranch
echo "test" > file2
git add .
git commit -m "created file2"
echo "test" >> file2
git add .
git commit -m "modified file2"

git checkout master
git cherry-pick a5d16cb4

What do we get? A conflict. And the error message tells us clearly what it is:

error: could not apply a5d16cb... modified file2
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'

Read the words. The problem is that C "modified file2". And the proposed solution is to add or rm the problematic file, file2.

Another way to see what the problem is, is to do at that point a git status. Here's what we get:

On branch master
You are currently cherry-picking commit a5d16cb.
  (fix conflicts and run "git cherry-pick --continue")
  (use "git cherry-pick --abort" to cancel the cherry-pick operation)

Unmerged paths:
  (use "git add/rm <file>..." as appropriate to mark resolution)

    deleted by us:   file2

Again, we are told that the issue is file2 and that the solution is to add or rm it. The phrase "deleted by us" is actually quite useful, and you can use it to express the problem in a possibly better way. Remember, we are trying to merge the diff B-to-A with the diff B-to-C. So, relative to B, which already has the file, A removes the file, while C modifies it. You cannot do both — that's the conflict.

So it's the file created and then modified on your second branch that's the issue. And that is why you see no conflict in the file created and modified on master; it isn't the conflict.



来源:https://stackoverflow.com/questions/60847892/git-cherry-pick-weird-issue-sometimes-conflicts-but-sometimes-not

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!