每当我有一个复杂的rebase时,因为我的当前功能分支有很多结论,而且我的功能分支有许多小的提交,所以解决过程似乎很麻烦,效率很低。
我一直在寻找在重新建立基础时从根本上压制before
的方法。一种解决方案似乎是对最后一次合并进行sofr重置,然后在多个提交中创建一个提交,然后再进行重新基准。
但这个解决方案似乎有点棘手。有更好的方法来处理这个问题吗。
编辑:我指的是必须通过拉请求进行合并的情况,而我无法控制合并过程本身。
正如您在评论中所做的那样,您可能想要git rebase -i
工作流。
运行git rebase -i <commit-to-keep>
本质上告诉Git:
- 列出当前分支上
<commit-to-keep>
之后的提交 - 针对每一项此类承诺,向
pick <hash>
提交一份说明单 - 一旦编辑了说明书,请查看
<commit-to-keep>
,然后按照说明进行操作 - 完成指令后,使当前分支指向最后一个这样的复制(或挤压或其他)提交
因此,如果您有一系列微小的提交A1, A2, A3
,然后是更多的B1, B2
,例如:
...--o--o <-- origin/feature
A1--A2--A3--B1--B2 <-- feature (HEAD)
并运行git rebase -i origin/feature
,Git会将所有五个提交哈希列为pick
指令。将A2
和A3
指令更改为squash
,同时将B2
指令更改为squash
,并保存生成的命令序列,将导致Git开始拾取和压缩提交。Git在A
组的最后一个停止一段时间,让您编辑提交消息,使您的编辑器看到新提交A
的消息,即A1+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]
编辑完提交消息后,它会再次恢复,并通过从旧链上"剥离标签"feature
并将其粘贴到新链上来完成分支更新:
A--B <-- feature (HEAD)
/
...--o--o <-- origin/feature
A1--A2--A3--B1--B2 [abandoned - in reflog as feature@{1}]
请注意,如果存在冲突,Git会以更大的暂停暂停重新定基(它实际上完全退出了git rebase
命令,但留下了很多跟踪文件,git status
可以使用这些文件来显示您仍处于重新定基的中间)。您必须修复冲突并运行git rebase --continue
以恢复操作。如果你只是压缩一些提交,你不应该看到冲突,但如果你重新安排了一堆分散的小冲突——也就是说,不是最初让所有的A
组在一起,而是分散在一起,然后你把它们聚集在一起——你可能会有小冲突需要解决。
在没有参数的情况下运行git rebase -i
告诉Git查找当前分支的"上游"设置。例如,如果feature
具有origin/feature
作为其上游,则这等效于git rebase -i origin/feature
。您总是将选定/编辑的TODO列表提交复制到某个指定的提交之后,但默认情况是"已设置的上游"。
请注意,在运行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
。你可以通过运行git log --all --decorate --oneline --graph
(使用"来自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
。
示例
以下回购有一个基于master
的分支feature/1
。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进行合并的情况下,因为必须通过pull请求进行合并。