简体   繁体   English

git cherry-pick 奇怪的问题,有时会冲突但有时不会

[英]git cherry-pick weird issue, sometimes conflicts but sometimes not

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:所以a0是初始提交,它有一个名为letter.txt的文本文件,其中包含一个字母a ,master 分支上的每个提交都附加下一个字母,因此m1中的letter.txt包含abm2包含abc ,然后我检查第二个分支,然后我添加了一个新文件,比如说bugfixcode.cs ,所以s1s2都是关于添加/修改bugfixcode.cs ,然后我切换回master ,发现我想从第二个中挑选一些提交分支,这里有一些奇怪的东西:

Q1.一季度。 if I cherry-pick s2, then it will be a conflict, but if I cherry-pick s1, then no conflict.如果我选择 s2,那么它会发生冲突,但如果我选择 s1,则没有冲突。 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 ?对于挑选s2时的冲突,我认为是因为第二个分支上的letter.txt的内容仍然a ,而m2上的文件有abc ,但这不是s1上的相同事实吗? why there is no conflict on s1为什么在s1上没有冲突

Q2. Q2。 For the conflict when cherry-picking s2 , why there is no conflict marker like <<<<<<< HEAD in letter.txt ?对于挑选s2时的冲突,为什么letter.txt没有像<<<<<<< HEAD这样的冲突标记? if there is no conflict marker , then there is no conflicts, isn't it?如果没有冲突标记,那么就没有冲突,不是吗?

This has nothing to do with letter.txt .这与letter.txt无关。 It's about bugfixcode.cs .这是关于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, ie HEAD ).它是一个合并,就好像目标提交的提交(在cherry-pick命令末尾命名的提交)是两个提交(目标提交和我们正在挑选的提交,即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.换句话说,它是差异(补丁)的重播(到HEAD ),让您从目标提交的父级到目标提交。

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."所以现在你尝试在 A 上挑选 C。这意味着:在 A 之上重放 B 到 C 的差异。你是说:“请对我做,A,你对 B 做了什么以获得 C .”

Well, what did you do to B in order to get C?哦,你为了得到c执行到B? What is the difference between B and C?什么B和C之间的区别? It's the modification of file x .是文件 x修改 But in A there is no file x at all!但是在 A 中根本没有文件 x! So what on earth does that mean?那么究竟是什么意思呢? How can we, starting with A, modify a file that isn't even there?我们如何从 A 开始修改一个根本不存在的文件? Git has no idea, so it throws up its hands. Git 不知道,所以它举起了手。

(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.) (如果您将 B 选到 A 上,则不存在相同的问题,因为很明显存在差异:创建文件。)

To see this in a controlled way, just play out the scenario.要以可控的方式看到这一点,只需播放场景即可。 Keep your eye on the file that I call file2 :请留意我称为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".问题是C“修改了file2”。 And the proposed solution is to add or rm the problematic file, file2 .建议的解决方案是addrm有问题的文件file2

Another way to see what the problem is, is to do at that point a git status .查看问题所在的另一种方法是在那时执行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.同样,我们被告知问题是file2 ,解决方案是addrm它。 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.请记住,我们正在尝试将差异 B-to-A 与差异 B-to-C 合并。 So, relative to B, which already has the file, A removes the file, while C modifies it.因此,相对于已经拥有该文件的 B,A删除该文件,而 C修改它。 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.因此,问题是在second分支上创建然后修改的文件。 And that is why you see no conflict in the file created and modified on master ;这就是为什么您在master上创建和修改的文件中没有看到冲突的原因; it isn't the conflict.不是冲突。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM