我正在尝试协调一个非常大的功能分支与多个团队和机构长期致力于的数百个提交。不幸的是,由于公司政策问题,不可能在团队之间强制执行一致的合并策略,因此现在分支不一致,包含大部分被压缩的合并以及数十个合并提交,这些合并提交创建了混乱的提交历史记录并在简单的
git rebase -i
上发生冲突
每当合并中的单个提交与在相似时间点并行处理的其他合并中的时间相邻提交发生冲突时。
我可以使用类似
git rebase -i --rebase-merges
之类的东西手动压缩所有提交和合并提交,但这会带来人为错误的风险,因为我需要手动重新排序数十个提交和合并提交,并且很容易意外将提交压缩到错误的合并提交或错误的顺序中。
Git 已经知道哪些提交属于哪些合并提交,因此应该可以通过自动化来消除人为错误的风险。我希望有像
git rebase --squash-merges
这样的东西,它会在每次提交到其合并提交时执行自动压缩,就好像该合并是压缩合并一样,但此功能似乎不存在(但可能可以编写一个使用列出每个合并提交的提交的命令以这种方式工作的命令链?)。
有什么方法可以让 Git 遍历分支中的提交,并以正确的顺序自动将松散的提交压缩到合并提交中,而不需要手动执行操作而冒人为错误的风险?
这是从
git rebase -i --rebase-merges some-branch
输出的第 300 行左右编辑的摘录示例。这里我们有两个合并,每个合并一次,还有两个压缩合并。由于提交和合并之间存在时间差距,定期变基会看到“make widget”和“Create McGuffin”之间的合并冲突。 :
pick af697c57 Release: 1.2.1
label branch-point-9
pick 3e50d3ae XYZ-32: Create McGuffin (#394)
label merge
# Branch org-XYZ-29-make-widget
reset branch-point-9 # Release: 1.2.1
pick 4d53b13c feat: make widget for XYZ-29
merge -C 0d9d6676 merge # merge
label org-XYZ-29-make-widget
# Branch merge-2
reset merge # XYZ-32: Create McGuffin (#394)
merge -C 04d11323 org-XYZ-29-make-widget # Merge pull request #400 from org/XYZ-29/make-widget
pick 060bbde5 XYZ-27: splice mainbrace (#399)
pick 50ae56cf XYZ-36: reticulate splines (#397)
label merge-2
我想将这个(以及每个这样的情况)压缩成这样的东西(应该没有冲突,因为任何冲突都已经在合并中解决了),使用 Git 已经知道哪些提交属于哪些合并提交以及如何提交的信息合并已得到协调:
pick af697c57 Release: 1.2.1
pick XXXXXXXX XYZ-32: Create McGuffin (#394) # commit squashed into its merge commit
pick YYYYYYYY Merge pull request #400 from org/XYZ-29/make-widget # commit squashed into its merge commit
pick 060bbde5 XYZ-27: splice mainbrace (#399)
pick 50ae56cf XYZ-36: reticulate splines (#397)
...我认为这可以通过在合并提交下仔细重新排序提交、压缩这些提交,然后选择压缩的合并作为常规提交,在交互式变基中手动实现?但大规模这样做会增加人为错误的风险。
Git 存储快照并记录每次提交的一个或多个父项。常规提交有一个父级,而合并提交有两个父级(或更多)。有了这些知识,您应该清楚地知道您想要重写提交以仅包含单个父级,以便历史记录变得线性。每个合并提交的快照已经指向合并结果。
通常的建议适用:不要重写已发布/共享的历史记录(并进行备份)。
filter-branch --parent-filter
可以做到这一点:
git filter-branch --parent-filter 'cut -f" " -d1,2' -- main..yourbranch
这将改变历史,例如:
x < yourbranch
|\
x x
| |\
|/ /
x x
|/
x < main
进入这个:
x < yourbranch
|
x x
| |
|/
x x
|/
x < main
请注意,您最终将得到无法访问的提交,但您可以简单地放弃它们。
在后续步骤中,您可能希望使用交互式变基来重写重写的合并提交,以包含合理的提交消息。