我理解为,挑选某个提交点进行精选会在目标分支中引入一个新的提交记录,其中包含了这个提交点的更改内容。
是的。但是,这些更改可能无法干净地应用,如果出现这种情况:
...... 我遇到了合并冲突。
此时,
git cherry-pick
正在执行三方合并,需要选择一个
合并基准。
你的 Git 版本会影响合并基础使用的文件或提交,据我所知。现代的 Git,如果你运行
git cherry-pick
命令,将使用被拾取的提交的
parent 作为
合并基础,但至少有一种形式(使用
git am
或
git apply
并带有
--3way
选项,这是
git rebase
仍然可以做到的),可以使用
git diff
输出中的
index
行来挑选出一个更早版本的文件。最终,这可能不太重要。
无论如何,合并将实际上从基础提交运行
git diff
到两个“提示”(挑选的提交和您试图应用挑选的提交的HEAD提交)。为了直观地看到正在发生的事情,您应该像往常一样开始绘制提交图。 (我没有您的存储库,因此我将绘制一个
不同的图形,并希望它足够接近。但是您应该绘制自己的图表-或者让Git做到这一点,或使用
gitk
或类似工具。)
o--@ <-- branch (HEAD)
/
...--o--o
\
I--P--C--o <-- otherbranch
我在这里为不同的提交分配了单个字母的名称:
C
是我们即将挑选的提交,
P
是其父提交。我将当前(HEAD)提交标记为
@
,尽管所有真正的工作都将在索引和工作树中进行。(幸运的是,
git cherry-pick
要求索引和工作树“干净”,除非您使用
-n
将多个挑选组合成一个大的挑选,因此索引和工作树将与提交
@
匹配。)我将提交
I
标记为“重要”。
现在,考虑如果我们以P
为基础,以C
作为其中一个提交,以@
作为另一个提交进行三方合并会发生什么。当我们计算将P
更改为C
的指令时,我们得到了要应用的差异:这很简单直接。但是当我们计算将P
更改为@
的指令时,嗯,有点麻烦。
我们对
I
进行了一些重要的更改。这些更改是
P
的一部分,也就是说,它们在我们的合并基础中。但是它们不在
@
中。对于合并,Git 将认为这些重要更改是我们试图撤消的事情。实际上,它们确实是!我们没有挑选
I
本身,因此我们必须撤消这些
I
更改,以应用来自
C
的更改。
无论那些我们正在“撤消”的I
更改是否起始于@
,并且不影响来自C
的任何更改,我们都没问题:它们已经被撤消了。如果偶然或有意地,其中一个I
更改位于@
中(可能是通过@
的父级),那么这些甚至不在我们首先尝试撤消的集合中,因此我们仍然没问题。当这些更改与P
到C
的更改发生冲突,甚至仅仅是接触到(上下文)时,我们就会遇到问题。
在这种情况下,Git将会在两个合并冲突区域之一中显示一些
更改。这些更改位于我们试图挑选的部分中,它们不一定被应用,只是我们必须解决的冲突的一部分。如果您将merge.conflictStyle
设置为diff3
(我通常建议这样做),那么更改将显示为合并基础的一部分,因为合并基础是提交P
,而P
本身就是基于I
的(即P
的快照包括来自I
的代码,除非我们在制作P
时对其进行了更改)。
所以,我不太清楚您所询问的内容,但在合并冲突区域中看到与您正在挑选的位无关的更改是正常的。
git cherry-pick
没有冲突合并,但修改后的文件却包含不应该存在的更改,同样的问题出现在使用补丁和git apply
时。 - angularsen