阻止 Git 快进自动合并

Prevent Git Fast Forward Automatic Merge

问题上下文示例:

  1. 分支 B 是从 A 分支
  2. 创建的
  3. 在分支 B 中创建并编辑了多次名为 XPTO.txt 的文件(多次提交)
  4. 另一个分支 C 是从分支 B 之后创建的
  5. 并行 XPTO.txt 在分支 BC[=60= 中再次被编辑多次(多次提交) ]
  6. 分支 C 必须合并回 A
  7. 从分支 C 到分支 A 的拉取请求 (PR) 不得包含来自 XPTO.txt 中的更改在创建分支 C 之前分支 B

假设删除 B 分支代码的这些更改(提交)正确完成并且不影响项目构建等

我应该如何正确管理存储库以便:

Scale the example to several files and several changes (commits).

到目前为止我认为唯一的答案是强制从分支 B 进行非 FF 合并到分支 A 但仍然得到Already up to date! 有时。

谢谢。

鉴于这些步骤:

  1. 分支 B 是从 A 分支
  2. 创建的
  3. 在分支 B 中创建并编辑了多次名为 XPTO.txt 的文件(多次提交)
  4. 另一个分支 C 是从分支 B 之后创建的
  5. 并行 XPTO.txt 在分支 BC[=71= 中再次被编辑多次(多次提交) ]

您的存储库看起来像这样:

                               (B)
                                |
                                v
                      <--b3 <--b4
                    /
a1 <--a2 <--b1 <--b2
       ^            \
       |             <--c1 <--c2
      (A)                      ^
                               |
                              (C)

小写标签是单独的提交,link通过它们的“父”引用(向后的箭头)组合在一起。大写标签是分支,在 git 的模型中只是指向特定提交的指针,可用于引用该提交及其所有祖先。

请注意,提交 b1 和 b2 最初是在分支 B 上创建的,但就 git 而言,它们只是分支 C 历史的一部分。

所以现在:

  • 从分支 C 到分支 A 的拉取请求 (PR) 不能包含在创建分支 C 之前从分支 B 在 XPTO.txt 中所做的更改

没有直接的方式告诉 git - 它不知道哪些提交“属于”分支 B 或“在”分支 C 之前。如果您要求将分支 C 合并到 A,它会回头直到找到一个共同的祖先,即 a2,因此要合并的提交是 b1、b2、c1 和 c2。

为了“删除”这些提交,您需要创建历史记录中没有它们的新提交。这就是“git rebase”命令的用途。

在这种情况下,您需要将“b2”之后的提交变基到“A”,因此命令为 git rebase b2 C --onto A。结果将如下所示:

                               (B)
                                |
                                v
                      <--b3 <--b4
                    /
a1 <--a2 <--b1 <--b2
      ^ \           \
      |  \           <--c1 <--c2
     (A)  \
           <--c3 <--c4
                     ^
                     |
                    (C)

现在提交 b1 和 b2 不再是 C 历史的一部分。

提交 c3 和 c4 将分别由基于 c1 和 c2 的 rebase 命令创建,但不要 link 以任何方式对它们进行修改。如果没有其他分支或标记指向提交 c1 和 c2,它们最终将作为孤立数据被“垃圾收集”。


如果您想要 部分 来自提交 b1 和 b2 的更改,您需要将它们作为新提交手动添加回来。这可能会或可能不会导致以后发生冲突,具体取决于合并算法是否可以弄清楚您要做什么。但这只是生活中的一个事实:对同一个文件的两个并行更改存在冲突的风险。


请注意,这与 还原 更改(使用“git 还原”,或手动撤消它们)有很大不同,后者会创建 额外的 历史记录:

                               (B)
                                |
                                v
                      <--b3 <--b4
                    /
a1 <--a2 <--b1 <--b2
       ^            \
       |             <--c1 <--c2 <--rb1 <--rb2
      (A)                                   ^
                                            |
                                           (C)

此处,“rb1”撤消了“b1”的更改,“rb2”撤消了“b2”的更改,但是所有四个提交 都是 C 历史的一部分。一旦你合并到 A,它们也将成为 A 历史的一部分,所以当你合并到分支 B 时,只有 b3 和 b4 是“新的”。

解决此问题的唯一其他方法是重新设置分支 B 以创建提交的新副本以在 恢复后合并。这导致了一段混乱的历史,但有时也是摆脱混乱的出路。

                               (B)
                                |
                                V
          <--b5 <--b6 <--b7 <--b8
        /
       |
       |             <--b3 <--b4
       |            /
a1 <--a2 <--b1 <--b2
       ^            \
       |             <--c1 <--c2 <--rb1 <--rb2
      (A)                                   ^
                                            |
                                           (C)

这里的b5、b6、b7、b8是b1、b2、b3、b4通过rebase命令重新创建的版本。