避免多重冲突解决的最佳方法 - Git 变基前软重置?

Best way to avoid multiple conflict resolutions - Git soft reset before rebase?

每当我有一个复杂的 rebase 时,因为我当前的功能分支有很多冲突,并且因为我的功能分支有很多小的提交,解决过程似乎很麻烦且效率低下。

我一直在寻找从本质上压制 before 变基发生的方法。一种解决方案似乎是将 sofr 重置为最后一次合并,然后从许多提交中创建一个提交,然后才进行 rebase。

但这个解决方案似乎有点老套。有没有更好的方法来处理这个问题。

编辑: 我指的是必须通过拉取请求完成合并​​并且我无法控制合并过程本身的情况。

正如您在评论中所做的那样,您可能需要 git rebase -i 工作流程。

运行 git rebase -i <commit-to-keep> 本质上告诉 Git:

  1. 列出当前分支上的提交,这些提交在 <commit-to-keep> 之后;
  2. 提出并指示 sheet 对每个此类提交说 pick <hash>
  3. 编辑指令 sheet 后,检查 <commit-to-keep> 然后按照说明进行操作;
  4. 完成指令后,使当前分支指向最后一个这样的复制(或压缩或其他)提交。

因此,如果您有一系列微小的提交 A1, A2, A3,然后还有一些 B1, B2,例如:

...--o--o   <-- origin/feature
         \
          A1--A2--A3--B1--B2   <-- feature (HEAD)

和 运行 git rebase -i origin/feature、Git 将所有五个提交哈希列为 pick 指令。将 A2A3 指令更改为 squash,并将 B2 指令更改为 squash,并保存生成的命令序列,导致 Git 开始 pick-and-squash-ing 提交。 Git 在 A 组的最后停下来让您编辑提交消息,在新提交 AA1+A2+A3 的消息上调出您的编辑器:

          A   <-- HEAD [in progress / being rebuilt]
         /
...--o--o   <-- origin/feature
         \
          A1--A2--A3--B1--B2   <-- feature [being rebased]

它现在自动恢复列表,这取决于 B 提交的说明。它再次暂停,启动您的编辑器,以提交新的一体机 B:

          A--B   <-- HEAD [in progress / being rebuilt]
         /
...--o--o   <-- origin/feature
         \
          A1--A2--A3--B1--B2   <-- feature [being rebased]

一旦您编辑了提交消息,它会再次恢复并通过 "peeling the label" feature 完成分支更新,从旧链上移除并将其粘贴到新链上:

          A--B   <-- feature (HEAD)
         /
...--o--o   <-- origin/feature
         \
          A1--A2--A3--B1--B2   [abandoned - in reflog as feature@{1}]

请注意,如果存在冲突,Git 会以更大的暂停时间暂停变基(它实际上完全退出了 git rebase 命令,但在 [=37] 后面留下了很多跟踪文件=] 可以用来表明你还在变基的中间)。您必须修复冲突并 运行 git rebase --continue 才能恢复。如果你只是压缩一些提交,你不应该看到冲突,但如果你正在重新安排一堆分散的小提交——即,而不是最初将所有 A 分组,它们 分散在各处,你把它们聚集在一起——你们可能有小冲突需要解决。


运行 git rebase -i 没有参数告诉 Git 查找当前分支的 "upstream" 设置。例如,如果 feature 的上游为 origin/feature,则等价于 git rebase -i origin/feature。你总是在一些指定的提交之后复制你选择的/编辑的 TODO 列表提交,但默认是 "the upstream you've already set".

请注意,您必须在 运行 宁 git fetch 之前完成所有这些操作,因为 git fetch 会更新 origin/feature .如果你做了 运行 git fetch,它确实更新了 origin/feature,你现在可能有:

          o--o--o   <-- origin/feature
         /
...--o--*   [remembered in your reflogs as origin/feature@{1}]
         \
          A1--A2--A3--B1--B2   <-- feature (HEAD)

如果是这种情况,您需要在提交 * 时明确 git rebase -i。您可以通过 运行ning git log --all --decorate --oneline --graph(使用 "help from A DOG",All Decorate Oneline Graph)找到它的散列,或者您可以使用它在您的 origin/feature reflog 中的事实作为 origin/feature@{1},通过以下方式验证:

git log --decorate --oneline --graph origin/feature@{1}..

("DOG" 仍然在那里,只是没有 --all 部分,以减少混乱。或者,您甚至可以使用 git merge-base 来定位提交 *,但我们将把它留到另一个主题。:-) )

您可以使用 git merge --squash feature_branch:

git checkout master
git merge --squash feature_branch

这会将 feature_branch 中的所有提交压缩为一个提交,并将这个提交添加到 master

例子

以下 repo 有一个分支 feature/1,它基于 master。在 feature/1 中有一些提交,在 master 中有一个提交。之后,我在 master 上做了一个 git merge --squash feature/1,它创建了提交 5497776,其中包含 feature/1.

上树提交的更改
* 5497776 (HEAD, master) merge --squash feature/1
* 46059c7 Change 2 on master
| * b080e96 (feature/1) Change 3 on feature branch
| * 6caf662 Change 2 on feature branch
| * 69d9993 Change 1 on feature branch
|/  
* b39b078 Change 1

顺便说一句,我明确地挑起了合并冲突。您可以在合并过程中解决它们,然后暂存更改以将冲突标记为已解决并继续 git commit

软重置为上次合并,然后创建一个新的提交是最好的解决方案。这已被严重否决,但我认为这是不合理的,特别是在无法直接合并到 master 的情况下,因为它必须通过拉取请求完成。