为什么这个 cherry-pick 有冲突?
Why does this cherry-pick have a conflict?
我知道 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'
然后我运行:
git diff
输出:
diff --cc a
index 7898192,de98044..0000000
--- a/a
+++ b/a
@@@ -1,1 -1,3 +1,6 @@@
a
++<<<<<<< HEAD
++=======
+ b
+ c
++>>>>>>> 11fff29... abc
所以我的问题是:为什么会出现像git-diff这样的冲突? cherry-pick在这种情况下工作的细节是什么?
从技术上讲,由于您是在不同分支上编辑同一文件的同一行,Git 将此视为冲突。 Cherrypicking,虽然在技术上不是 'merge' 操作,但仍然会寻找相同类型的冲突并要求您解决它们。
For conflicting paths, the index file records up to three versions, as described in the "TRUE MERGE" section of git-merge[1]. The working tree files will include a description of the conflict bracketed by the usual conflict markers <<<<<<< and >>>>>>>.
在:
之后再试一次你的选择
git config merge.conflictstyle diff3
您将获得更详细的差异:
<<<<<<< HEAD
||||||| parent of 5b2a14c... dev add line c
b
=======
b
c
>>>>>>> 5b2a14c... dev add line c
这表明,当应用由dev
的HEAD(b
和c
)表示的补丁时,Git不知道一个共同的祖先;它遵循:
- 精心挑选的提交的直接父级(表明它添加了一行'
c
'after a line 'b
')
- 目标提交(根本没有显示行
b
可以在其上应用添加的更改“c
”)
因此冲突。
Cherry-picking is not like a merge (which looks for a merge-base).
Cherry-picking 提交并应用它引入的更改。
这里引入的变化是:在b
之上添加c
。
并且目标提交根本没有 b
,所以对于 Git:
- 上游(目标)提交有 "removed
b
"(或者一开始就没有,这里就是这种情况,但 Git 不知道),
- 源代码提交有一个
b
,其上添加了 c
。
据 Git 所知,何时尝试应用该补丁(这就是 git cherry-pick
所做的全部:应用补丁。它根本不查找精心挑选的提交的历史记录),即冲突:并发修改。
如果您确定解决方案应该采用的方式,您可以这样做:
> 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(+)
然后,您会看到 b
和 c
添加到原始提交中,没有任何冲突(因为您指出了如何使用传递给的选项 '-Xtheirs
' 来解决它default merge strategy recursive
)
我知道 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'
然后我运行:
git diff
输出:
diff --cc a
index 7898192,de98044..0000000
--- a/a
+++ b/a
@@@ -1,1 -1,3 +1,6 @@@
a
++<<<<<<< HEAD
++=======
+ b
+ c
++>>>>>>> 11fff29... abc
所以我的问题是:为什么会出现像git-diff这样的冲突? cherry-pick在这种情况下工作的细节是什么?
从技术上讲,由于您是在不同分支上编辑同一文件的同一行,Git 将此视为冲突。 Cherrypicking,虽然在技术上不是 'merge' 操作,但仍然会寻找相同类型的冲突并要求您解决它们。
For conflicting paths, the index file records up to three versions, as described in the "TRUE MERGE" section of git-merge[1]. The working tree files will include a description of the conflict bracketed by the usual conflict markers <<<<<<< and >>>>>>>.
在:
之后再试一次你的选择git config merge.conflictstyle diff3
您将获得更详细的差异:
<<<<<<< HEAD
||||||| parent of 5b2a14c... dev add line c
b
=======
b
c
>>>>>>> 5b2a14c... dev add line c
这表明,当应用由dev
的HEAD(b
和c
)表示的补丁时,Git不知道一个共同的祖先;它遵循:
- 精心挑选的提交的直接父级(表明它添加了一行'
c
'after a line 'b
') - 目标提交(根本没有显示行
b
可以在其上应用添加的更改“c
”)
因此冲突。
Cherry-picking is not like a merge (which looks for a merge-base).
Cherry-picking 提交并应用它引入的更改。
这里引入的变化是:在b
之上添加c
。
并且目标提交根本没有 b
,所以对于 Git:
- 上游(目标)提交有 "removed
b
"(或者一开始就没有,这里就是这种情况,但 Git 不知道), - 源代码提交有一个
b
,其上添加了c
。
据 Git 所知,何时尝试应用该补丁(这就是 git cherry-pick
所做的全部:应用补丁。它根本不查找精心挑选的提交的历史记录),即冲突:并发修改。
如果您确定解决方案应该采用的方式,您可以这样做:
> 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(+)
然后,您会看到 b
和 c
添加到原始提交中,没有任何冲突(因为您指出了如何使用传递给的选项 '-Xtheirs
' 来解决它default merge strategy recursive
)