Git 为什么这个樱桃选择有冲突?

Git 为什么这个樱桃选择有冲突?,git,cherry-pick,git-cherry-pick,Git,Cherry Pick,Git Cherry Pick,我知道git cherry pick是一个用于应用指定提交更改的命令,但我认为我并不真正理解它的工作方式 假设回购协议的行为是这样的: git init echo a>a git add .; git commit -am 'master add line a' git checkout -b dev echo b>>a git commit -am 'dev add line b' echo c>>a git commit -am 'dev add line

我知道
git cherry pick
是一个用于应用指定提交更改的命令,但我认为我并不真正理解它的工作方式

假设回购协议的行为是这样的:

git init

echo a>a
git add .; git commit -am 'master add line a'

git checkout -b dev
echo b>>a
git commit -am 'dev add line b'
echo c>>a
git commit -am 'dev add line c'

git checkout master

git cherry-pick dev
我认为
cherry pick
命令会很好地工作,并将文件
a
更改为:

a

c
但事实上,我得到了以下信息:

error: could not apply 08e8d3e... dev add line c
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'
输出:

diff --cc a
index 7898192,de98044..0000000
--- a/a
+++ b/a
@@@ -1,1 -1,3 +1,6 @@@
  a
++<<<<<<< HEAD
++=======
+ b
+ c
++>>>>>>> 11fff29... abc
diff--cc a
索引7898192,de98044..0000000
---a/a
+++b/a
@@@ -1,1 -1,3 +1,6 @@@
A.
++>11fff29。。。abc

所以我的问题是:为什么会有像git diff shows这样的冲突?cherry pick在这种情况下工作的细节是什么?

从技术上讲,由于您在不同的分支上编辑同一文件的同一行,Git将此视为冲突。Cherrypicking虽然从技术上讲不是“合并”操作,但仍然会查找相同类型的冲突并要求您解决它们

对于冲突路径,索引文件最多记录三个版本,如git MERGE[1]的“TRUE MERGE”部分所述。工作树文件将包括由常用冲突标记>括起的冲突描述


再次尝试您的樱桃采摘:

您将获得更详细的差异:

<<<<<<< HEAD
||||||| parent of 5b2a14c... dev add line c
b
=======
b
c
>>>>>>> 5b2a14c... dev add line c

然后,您将看到添加到原始提交中的
b
c
,没有任何冲突(因为您指出了如何使用传递给的选项“
-Xtheirs
”来解决问题)

Git cherry pick是一种选择并将来自另一个分支的单个提交应用到当前分支的方法。它本质上是对一个提交进行合并,因此可能会产生冲突。您看到的内容不一定有任何错误。@TimBiegeleisen但如果我运行
git merge dev
,则没有冲突,表明我成功地合并了…
git cherry pick dev
对我来说根本没有意义,因为您指定的是分支名称而不是提交。@TimBiegeleisen
dev
指的是分支
dev
的最后一次提交,所以我认为
git cherry pick dev
没有什么问题。考虑合并多个提交,比如连续进行小更改。在这种情况下,可能没有冲突,因为Git可以处理每个小的更改。当您选择最新的提交时,Git可能会看到一些戏剧性的事情,如果没有手动干预,它将无法解决这些问题。这是一种解释。嗯……我不认为我编辑了同一文件的同一行,只是在文件的末尾添加了几行。不确定为什么这个答案在最后几分钟内获得了两张赞成票:这并不能解释cherry pick是如何在同时发生更改的情况下结束的。它只说明了显而易见的情况(即:“并发更改意味着冲突,如果冲突,Git会要求您解决”)。所有的问题都是“Git如何得出并发更改的结论?”。巧合的是,冲突错误消息正在重写和讨论,正如我们所说:“cherry picked commit的直接父级(表明它在“b”行之后添加了一行“c”)是我对其工作方式的怀疑,但我也认为git会足够聪明,能够识别它在文件的最后一行,这样就不会发生冲突。git是否总是按照上面的线放置?@JeffPuckettII与其说它是“上面的线”,不如说它是“樱桃树与其直接父树之间的补丁”。这里,最后一个
dev
commit与其父级之间的增量是“
c
”,位于“
b
”之上。它应用于最后一行的事实在这里并不重要。Git在相关行附近找不到“
b
”(在
HEAD
上应用修补程序时)这一事实很重要。我知道,要应用更改,Git将计算一个修补程序,该修补程序不仅包括更改的行,还包括其周围的一些上下文行?我在对您答复的另一个答复中提到了这一点,但是:
git cherry pick
实际上使用了一个合并基并进行了三方合并。这里的问题是,在许多(但不是所有)情况下,合并基本身是非常虚假的,因此没有帮助,甚至可能是有害的。这意味着Git首先尝试一种简单的“直接补丁”方法。如果失败,它将返回使用提交的父提交作为合并基础。有时,这允许补丁正确应用,特别是如果“基础”确实在当前历史记录中。
git config merge.conflictstyle diff3
<<<<<<< HEAD
||||||| parent of 5b2a14c... dev add line c
b
=======
b
c
>>>>>>> 5b2a14c... dev add line c
> git cherry-pick -Xtheirs dev
[master 7849e0c] dev add line c
 Date: Wed Aug 17 08:25:48 2016 +0200
 1 file changed, 2 insertions(+)