假设我正在开发一个涉及更改系统多个组件的功能。举个例子,假设我需要更新守护进程、服务器和客户端。我目前的工作流程会给我留下这样的分支/提交:
m1---m2---m3 <- master
d1---d2 <- daemon
s1---s2 <- server
c1---c2 <- client
有了这些分支,我可以在GitHub上创建3个拉请求,合并client -> server
、server -> daemon
和daemon -> master
。这一切都很好,直到我需要在client
以外的分支上添加提交为止。例如,假设我在daemon
:上进行了一次提交
m1---m2---m3 <- master
d1---d2---d3 <- daemon
s1---s2 <- server
c1---c2 <- client
现在我只剩下";rebase地狱";,其中我需要将server
重定为daemon
,将client
重定为server
,等等。有没有办法将s1
移动到d3
,并在一个命令中使用像client
这样的下游分支?因此,留下了这样的最终状态和我的拉取请求:
m1---m2---m3 <- master
d1---d2---d3 <- daemon
s1---s2 <- server
c1---c2 <- client
它可能感觉像是"rebase地狱";,但实际情况是,您只需要一个rebase命令,然后只需要将中间的分支重新指向它们各自的新提交。因此,这是一个rebase命令,后面跟着n-2
分支重置,其中n
是您将拥有的PR(分支(的数量。在你有3个分支的例子中,它有点像两行:
git rebase d2 client --onto d3
# Now for each middle branch, reset to the corresponding new commit ID:
# Look at the log of client to see the new s2 ID
git branch -f server <new-commit-id-of-s2>
如果你有许多分支以这种方式链接,或者你需要经常这样做,如果需要的话,你当然可以自动重置部分(例如,提交消息和作者姓名/日期将相同,等等(。然而,考虑到以这种方式进行分支(通常(是一种理论上的反模式,我希望这种情况不会经常发生,从而保证花费太多时间来自动化一些可以足够快手动完成的事情。
理论上,如果以这种方式进行分支,您只需要将daemon
和client
与master
合并,但这并不是一种理想的拆分工作方式,除非每个上游更改都依赖于前一个组件,即使这样,您也可能希望为整个功能发布/合并保存集成,而不是在每个子组件上进行集成。
在示例2中,除了d3
之外的所有提交都已在client
中,因此您可以将工作流简化为1、2或3个步骤:
-
示例1:合并
client -> master
会带来一切 -
示例2:合并
client -> master
会带来除d3
之外的所有内容。Cherry pick(或rebase commit only(d3
到客户端或主机 -
示例2(可选-最简单(:合并
daemon -> client -> master
将产生d3
和server
-
示例2(alt 2(:在下游PR(
client -> master
(之前合并上游分支(daemon
,server
(
更安全的方法可能是简单地分支master一次以创建集成分支,然后分支并合并(在解析时(每个组件,这样您就可以在不更新生产分支的情况下测试它们的互操作性。这将是您进行审查的地方,然后在发布准备就绪后将其合并以掌握。
当然,这意味着多合并1个,而不是更少,但不会涉及分支功能链接,并且在发布前更容易发现错误。有时,你不想要最少的合并或最干净的历史记录,你想要的是护栏。