压缩一些被合并跟随的提交

3
在一个git仓库中,我有一个分支,我经常将主分支合并到这个分支中:
A -- B -- C -- D -- E -- F -- G (master)
 \         \              \ 
  U -- V -- M1-- X -- Y -- M2 -- Z  (feature)

在哪里,M1M2提交将master合并到feature
我想压缩连续的提交UV,并保留其余的结构。
直观地说,这应该是可能的,而不必再次解决M1M2中的合并冲突,因为通过将UV压缩在一起,我不会改变被M1合并的工作树的状态,也不会改变合并基础。
然而,如果我使用git rebase -i A --rebase-merges(选择pick U,然后是fixup V)来做这个,我需要再次解决M1的合并冲突。
有没有办法告诉Git重复使用M1和后续的提交?

直觉上,应该可以在不再解决M1和M2中的合并冲突的情况下完成这个操作。但事实并非如此。你不能“重用”提交。Git的提交是不可变的,包括它们的父子关系。因此,在压缩后的提交之后,包括合并提交在内的所有提交都必须由Git构建全新的提交来替代。所以合并必须重新执行。rerere可以帮助重复相同的合并冲突解决,但可能对你现在没有帮助,因为你没有启用它。你只能忍受一下,再次解决冲突。 - undefined
我明白这些提交会获得新的ID,但我的意思是,在这些提交中,工作树的状态应该与重新基于之前的相应提交的状态完全相同。 - undefined
直觉上,应该可以在不再解决M1和M2中的合并冲突的情况下完成这个操作。从概念上讲是可以的,git rebase --rebase-merges可能会在某个时候具备这种能力。但目前实现的方式是将提交应用到代码中,并不关心“之前”的解决方案。 - undefined
是的,你必须解决任何冲突才能构建它。 - undefined
1
请参阅https://dev59.com/vVUL5IYBdhLWcg3w-sR4 - undefined
1
理想情况下,你可以使用基于快照的重写工具来完成这个任务,因为你只需要创建具有不同父节点的新提交:将 V 的父节点从 U 改为 A,然后重新计算传递子节点。对于这种用例来说,git rebase 并不是很适合(而且速度也比较慢)。 - undefined
1个回答

0
正如评论中指出的那样,git无法检测到要合并的两个提交恰好与我们已经知道的另外两个提交的文件树状态相同。
Git的rerere工具对解决一些合并冲突很有帮助,但根据我的经验,即使合并与先前的合并完全相同(例如,某些文件在一侧被删除),它仍然可能留下一些冲突未解决。
然而,可以强制git重用先前合并提交的内容。我编写了一个小脚本来帮助处理这个问题,在冲突合并的rebase过程(使用--rebase-merges启动)停止后使用。
如果你处于这样的状态:
$ git status
interactive rebase in progress; onto 123ab26c2a
Last commands done (123 commands done):
   pick 3baea80fd Change some files
   merge -C bb894b46f main-2 # Merge branch 'main' into feature
  (see more in file .git/rebase-merge/done)
...

您可以随后调用此脚本。
reuse_commit bb894b46f

该命令检查所提供的提交是否为合并提交,并且其父提交与当前要合并的提交(HEAD和MERGE_HEAD)具有相同的内容。如果这些内容匹配,则检索合并提交的内容并使用它创建一个新的合并提交(具有相同的元数据)。然后,您可以使用git rebase --continue命令继续操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接