Cherry 通过合并提交选择一系列提交

Cherry pick a range of commits with merge commits

我需要挑选一系列提交,但它失败了,因为在这个范围内我合并了一些分支。 有没有可能做到不冲突?

Is it possible to do it without conflicts?

这取决于转换为变更集的提交中的内容,以及您当前提交中的内容。这也不是我关心的真正问题。

... it fails because in this range I have merge [commits]

大概你的意思是 git cherry-pick 在到达合并提交时抱怨你没有指定 -m 参数。如果您 do 指定了一个 -m 参数 (git cherry-pick -m 1 ...),Git 会抱怨您 did 指定了一个-m 那些 不是 合并的提交的参数。这确实是一个 conundrum:您必须指定 -m 1,同时还要省略 -m 1

这个问题的直接解决方案是逐个挑选:选择第一个但许多非合并提交(以正确的顺序并且没有 -m 参数),然后是任何合并提交(以正确的顺序使用正确的 -m 参数,几乎总是 -m 1),然后是那些后面的任何非合并提交,然后是任何合并提交,依此类推。

不过,考虑一下每个 git cherry-pick 实际上 做的事情: 它包括合并 "what they did" 和 "what you did",其中 "what they did" 是父提交和子提交之间的差异, "what you did" 是父提交和您当前提交之间的差异。这里的父子就是我们给git merge命令的参数的父子。如果该参数指定合并提交,我们还必须指定 which parent——它不再只是 the parent——因此需要 -m 标志。但是挑选合并意味着我们应该合并的另一部分引入的所有更改

这意味着在许多情况下,您会希望在挑选时跳过所有合并提交。

例如,假设我们有一个如下所示的图表:

...--A--B--C--D---E--I   <-- feature-A
      \  \       /
       \  F--G--H
        \
         J--K--L   <-- feature-B (HEAD)

我们当前的提交是提交 L。由于某些特殊原因,我们希望获得等同于 FH 的 cherry-picking 提交,作为我们在 L 上添加的一个大提交或三个小提交,给予:

...--A--B--C--D---E--I   <-- feature-A
      \  \       /
       \  F--G--H
        \
         J--K--L--FGH'   <-- feature-B (HEAD)

其中 FGH' 是三个提交序列 (F'-G'-H') 或与其他三个执行相同操作的单个提交。

我们可以通过使用 git cherry-pick 并指示 Git 复制提交 FGH 来获得此信息。请注意,根本不需要 -m 标志,因为其中 none 是合并提交。如果我们使用 -n 来抑制提交每个单独的选择,并在最后做我们自己的 git commit,我们会得到一个大的 FGH' 提交。 (如果我们让 git cherry-pick 进行单独提交,当然,我们得到 F' 然后 G' 然后 H'。)

,我们可以使用合并提交E 来代替cherry-pick。合并提交 E 两个 父项,即 DH。如果我们查看 DE 之间的比较,我们将看到的更改是 通过 F-G-H 序列 导入的所有更改。因此,作为单个提交,我们很可能会获得 F-G-H 序列的副本。如果我们只想要 一次提交,那可能是可行的方法。它只是一个 git cherry-pick 而不是三个,所以肯定更容易。

但有一个警告:这会自动排除 已经通过C-D 序列达到E 的任何更改。例如,假设从 CD 的变化类似于从 BF 的变化,因此 D 包括 F 中的所有内容。那么DE的差值只是FGGH的差值之和。 (换句话说,B vs H 显示了 F-G-H 序列中发生的事情,但是 B vs D 包括 F 中发生的所有事情。因此 DE 有效地 隐藏了 F 的变化,因为它们已经在 D.) 中挑选合并因此会得到一个单一的提交,它具有 GH 组合的效果,但缺少 F这可能就是您想要的。它可能不是你想要的。此操作没有单一的通用公式。您必须检查有问题的提交并思考问题,而不是在这里盲目地应用一些过程。

无论如何,您现在已经拥有了思考问题和选择解决方案所需的工具。