挑选一个提交是否包括之前的提交?

9

在完成https://learngitbranching.js.org之后,我以为自己已经理解了cherry-pick的概念,但事实证明我完全没有。

我创建了一个名为abc.txt的文件,并按照以下步骤进行提交:

(write a) ← (write b) ← (write c)[master][HEAD]

通过这个过程,abc.txt 就变成了:

a
b
c

现在,从`from-a`(分支)上创建`write a`的分支。
(write a)[from-a][HEAD] ← (write b) ← (write c)[master]

经过挑选 (write c)[master],我认为这将使abc.txt只包含a行和c行,即像这样:

a
c

但实际上结果是这样的:
a
<<<<<<< HEAD
=======
b
c
>>>>>>> 3a0882d... write c

我的困惑有两个方面。为什么会冲突,而不是只添加这一行代码?为什么它包含了 b-line,尽管我只挑选了 write c


我认为这是因为git提交不是“更改”,而是文件的快照? - evolutionxbox
@evolutionxbox 我知道,但如果这有意义的话,我就不明白 cherry-pick 的意义是什么了... - akai
我不同意你的说法:“它根本没有做到”。Git 正确地注意到您正在尝试应用的补丁无法干净地应用,并告诉您有关冲突的信息,并要求您解决。这似乎是适当的行为。 - William Pursell
2个回答

9

Git具有上下文感知能力,会查找周围的行以及新增/删除的行。这是有意义的,因为git需要知道提交中的更改应该应用到哪里。

在你的情况下,分支from-a具有以下内容

 a

周围的行是空的。

您尝试挑选的提交具有以下内容:

diff --git a/abc.txt b/abc.txt
index 422c2b7..de98044 100644
--- a/abc.txt
+++ b/abc.txt
@@ -1,2 +1,3 @@
 a
 b
+c

即使提交信息显示了添加/删除行周围更广泛的上下文,Git 仍然只会尝试匹配修改上方和下方的一行。
(感谢 das-g
这意味着 Git 将尝试查找该行:
b

在文件的末尾插入该行

在文件末尾插入该行

c

在这之后。

由于在你的分支 from-a(当前的HEAD)上,git找不到这行代码。

b

由于文件结尾处存在冲突,你的补丁无法被完整应用,导致了冲突。

这段文字

<<<<<<< HEAD
=======
b
c
>>>>>>> 3a0882d... write c

表示Git检测到文件末尾的实际内容为空,由

标记表示的冲突。
<<<<<<< HEAD
=======

但是git期望找到这一行。
b

为了添加这行代码:
c

在此之后,由

指示。
=======
b
c
>>>>>>> 3a0882d... write c

这里留下了需要你解决的冲突,并决定如何合并这两个状态。

当出现冲突时,您总是寻找位于的代码,即<<<<<<< HEAD>>>>>>>之间的代码。
在它们之间,您将看到=======,这将当前HEAD状态和Git预期应用补丁后的状态分开。


0

cherry-pick 是一种合并操作。

提交 cc 的基础提交不同,它添加了行 c

提交 a 也与 c 的基础提交不同,它删除了行 b

                          file  [b]
                          ----
                          a
                          b


   file [a]                                  file [c]
   ----                                      ----
   a                                         a
                                             b
                                             c

由于两个更改块重叠,Git 假定受影响的行可能相关,因为源代码中的语义实体通常占用多行。您可能正在一个更改中添加到实体并在另一个更改中删除整个实体,行 c 可能与行 b 有关,如果您要删除 b ,则可能不希望添加 c 。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接