挑选一个提交包括以前的提交?
cherry-picking a commit includes previous commits?
完成 https://learngitbranching.js.org 后,我以为我得到了 cherry-pick 的想法,但事实证明我根本没有。
我创建了一个文件 abc.txt
并进行了如下提交:
(write a) ← (write b) ← (write c)[master][HEAD]
由此 abc.txt
变为:
a
b
c
现在,在 (write a)
上创建分支 from-a
:
(write a)[from-a][HEAD] ← (write b) ← (write c)[master]
和 cherry-picking (write c)[master]
,我认为它会让 abc.txt
只包含 a 线和 c 线,即像
a
c
但实际结果为:
a
<<<<<<< HEAD
=======
b
c
>>>>>>> 3a0882d... write c
在这里,我的困惑有两个方面。为什么它会发生冲突而不仅仅是添加行?为什么它包含 b 线,即使我只挑选了 write c
?
Git 是上下文感知的,会查找周围的线条以及 added/removed 的线条。
这是有道理的,因为 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
即使提交消息在 added/removed 行周围显示更广泛的上下文,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 预期的状态分开。
cherry-pick 是合并。
提交 c
不同于 c
的基本提交,它添加了行 c
.
commit a
也不同于 c
的基本提交,它删除了行 b
.
file [b]
----
a
b
file [a] file [c]
---- ----
a a
b
c
由于两个更改大块重叠,Git 假定受影响的行可能是相关的,因为源代码中的语义实体通常占用多行,您可能会在一次更改中添加到一个实体并删除整个实体另一方面,第 c
行可能与第 b
行有某种关联,如果您要删除 b
,您可能也不想添加 c
。
完成 https://learngitbranching.js.org 后,我以为我得到了 cherry-pick 的想法,但事实证明我根本没有。
我创建了一个文件 abc.txt
并进行了如下提交:
(write a) ← (write b) ← (write c)[master][HEAD]
由此 abc.txt
变为:
a
b
c
现在,在 (write a)
上创建分支 from-a
:
(write a)[from-a][HEAD] ← (write b) ← (write c)[master]
和 cherry-picking (write c)[master]
,我认为它会让 abc.txt
只包含 a 线和 c 线,即像
a
c
但实际结果为:
a
<<<<<<< HEAD
=======
b
c
>>>>>>> 3a0882d... write c
在这里,我的困惑有两个方面。为什么它会发生冲突而不仅仅是添加行?为什么它包含 b 线,即使我只挑选了 write c
?
Git 是上下文感知的,会查找周围的线条以及 added/removed 的线条。
这是有道理的,因为 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
即使提交消息在 added/removed 行周围显示更广泛的上下文,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 预期的状态分开。
cherry-pick 是合并。
提交 c
不同于 c
的基本提交,它添加了行 c
.
commit a
也不同于 c
的基本提交,它删除了行 b
.
file [b]
----
a
b
file [a] file [c]
---- ----
a a
b
c
由于两个更改大块重叠,Git 假定受影响的行可能是相关的,因为源代码中的语义实体通常占用多行,您可能会在一次更改中添加到一个实体并删除整个实体另一方面,第 c
行可能与第 b
行有某种关联,如果您要删除 b
,您可能也不想添加 c
。