樱桃采摘合并提交时的主线 parent 号

Mainline parent number when cherry picking merge commits

假设这是我的git历史

  Z
 /
A -- C -- D
 \  /      
  B

我的 HEAD 目前在 Z。我要 cherry-pick BC。如果我的理解是正确的,我应该这样做:

git cherry-pick B
git cherry-pick C -m 1
git commit --allow-empty

它在我的案例中起作用,因为 C 是一个 no-op(因此之后的空提交,我出于其他原因需要提交),但我想知道 [=16 之后的参数是什么=] 确实如此。这是我从 the docs:

读到的内容

-m parent-number

--mainline parent-number

Usually you cannot cherry-pick a merge because you do not know which side of the merge should be considered the mainline. This option specifies the parent number (starting from 1) of the mainline and allows cherry-pick to replay the change relative to the specified parent.

在我的例子中,C 有两个 parents 但我怎么知道哪个是 1 和 2,更重要的是,我选择 1 还是 2 什么时候重要?

我的理解是 this answer 是父 1 是被合并到的分支,父 2 是被合并的分支。因此,在您的情况下,父项 1 是 A,而父项 2 是 B。由于 cherry-pick 实际上是在两次提交之间应用差异,因此您使用 -m 1 仅应用来自 B 的更改(因为 AC 之间的差异包含变化自 B)。在您的情况下,这可能无关紧要,因为您在 AC.

之间没有提交

所以是的,-m 1 是你想要的,即使在 AC 之间有额外的提交也是如此。

如果你想让新的历史看起来更像原来的历史,还有另一种方法:

git cherry-pick B
git checkout Z
git merge --no-ff --no-commit B
git commit --author="Some Dev <someone@example.com>" --date="<commit C author date>"

(如果需要,您可以在挑选之前为 B 创建一个新分支。)

这将保留作者信息,应该给你一个看起来像这样的历史:

    B'
   /  \
  Z -- C'
 /
A -- C -- D
 \  /      
  B

我投了赞成票 ,这是正确的,但我只是想添加对包含 parent 编号的 ASCII 艺术的尝试。给定一个看起来像这样的图表:

       B
      / \
...--A   D--...
      \ /
       C

我们可以判断节点 D 是合并提交,但我们无法判断 BC 是否是 D 的第一个 parent .两者其中一个必然是第一个parent,另一个就是第二个。所以如果我们需要知道,我们必须给图贴上标签,这会占用更多的空间。这是一个这样的尝试。

         B
       /   \²
...--A       D--...
       \   /¹
         C

我们现在看到,出于某种原因,1 我画了图 "upside down":提交 C 实际上是第一个 [= D 的 60=],而提交 B 是第二个 parent。

可以使用较低级别 ("plumbing") 命令创建任意合并。特别是,git commit-tree 只接受您希望给它的许多 -p 个参数,按照您给它们的顺序,并使用给定的提交作为其 parent 进行新的提交。给它一个 -p,它用一个 parent 进行普通提交。不给它 -p 个参数,它会进行根提交。给它 155 个不同的 -p 参数(所有参数当然都必须解析为有效的提交 ID),它会产生一个巨大的章鱼合并提交。

然而,git merge 命令总是进行新的提交,第一个 parent 是当前的 HEAD(因此是当前分支,如果在分支上)。对于标准 two-parent 合并,第二个 parent 来自 .git/MERGE_HEADgit merge 将另一个提交 ID 写入其中。如果合并有冲突,或者最终合并提交延迟 --no-commit,这个 MERGE_HEAD 文件实际上是 唯一 提交 ID 可用的地方。

(当 git merge 进行章鱼合并时,使用 -s octopus 策略——这种策略被强制用于此类合并——以及多个额外的 parents,它中止并且不留下如果存在合并冲突,则完全跟踪,因此永远不会发生冲突情况。我没有尝试将 --no-commit 与章鱼合并结合使用,但从逻辑上讲,这会留下第 2 到第 N 个 parents在 MERGE_HEAD 中,如果 Git 允许这样做。)


1固执。