git 做单版本在线的项目是很成熟的,流程很清晰,每个issue创建一个branch,然后合并到master,打tag即可。
比如web项目,发布了1.0.0,然后修bug发布1.0.1、 1.0.2,新功能1.1.0、 1.2.0,改版大功能2.0.0 。只有一个版本在维护,一般不会出现 1.0.0 和 2.0.0 同时都在发布新版的情况。
git简单流程:IT虾米网
复杂点的流程:IT虾米网
但多版本并行发布的时候怎么办?
以Ubuntu系统为例,14.04 、 14.10 、 15.04 同时存在,14.10发布后,14.04也在持续的发布新版,比如14.04.1 、 14.04.2。
如果按照上面的git简单工作流程:
14.04在master里打tag发布了,下一个里程碑是14.10,很多人开发了很多分支,然后合并到master里,每天发布daily build版,看起来很美好。
突然,14.04有个紧急bug要修复,不可能等几个月等到14.10发布时带着一起修复,需要发布14.04.1那怎么办?从哪里checkout 14.04的代码?即使从tag里checkout下来了,修复完毕,合并到哪里?只能合并到master,但master是14.10,不能发布啊。
如果按照git复杂流程:
14.04在master里打tag发布了,下一个里程碑是14.10,很多人开发了很多分支,然后合并到develop分支里,每天发布daily build版。
突然,14.04有个紧急bug要修复,从master拉一个分支叫做hotfix-xxx,修复完毕,合并到master,打tag,发布14.04.1 。也合并到develop。
当14.10开发完毕,打算发布时,从develop拉一个分支叫做release-14.10,收尾完毕,把release-14.10合并到master,打个tag,发布了。也合并到develop,看起来很美好。
突然,14.04又有个紧急bug要修复,需要发布14.04.2怎么办?从哪里checkout 14.04.1的代码?即使从tag里checkout下来了,修复完毕,合并到哪里?只能合并到master,但master是14.10啊。
难道是每个版本一个项目? 比如 14.04 、14.10 、15.04 是3个项目?
这样感觉很奇怪,不优雅。请教大家有没有什么好办法。
另外提醒你一件事情:master 不是什么特别的分支,只是恰好被选作默认分支的名称而已。在 git 的模型中,所有分支都是平等的,没有那种分支会比较特别一些。从这个角度来说,你对 master 现有的困惑同样可以应用在其他任何一个分支上,如果你头脑中明白了这个模型,现在看问题的角度是否不一样了?
有些时候如果我们发现事情的发展已然导致当前的 master “废了”,要合理恢复它很困难,那么更容易的手段是直接把更合适的分支更名为 master 让它替代之前的那一个分支。聪明的你大概已经想到一些可能性了吧?在开发/工程的世界里,复杂的永远不是工具而是人,思考陷入僵局的时候就得学会跳出“自己”。
我们再换一个角度,假定“同一个bug不一定能merge到多个版本分支里”这个命题是成立的,我们不得不把多个版本分拆成多个项目,那么问题能否解决呢?或者会不会变得好一些呢?显然不可能。即使分拆为多个项目,多个版本需要共同修复同一个 bug 的现象始终存在。现在没有了 Git 辅佐,请问你要怎么处理呢?一个一个手动修补吗?
问题就在于你说的“不一定能merge到多个版本分支里”,你是怎么得出这个结论的呢?我能想象到由于管理和操作不当会引发各式各样的麻烦,有个麻烦甚至相当头疼,但终究都能找到合理的解决办法。因此我只能认为发出此问者的 Git 技能不够硬了——当然,Git 不是完美的,任何时候都算真理。
从tag:v14.04
拉一个分支叫branch:14.04.1-dev
,在里面进行开发,稳定以后打上tag:v14.04.1
就好,不用拘泥于“分支=>开发=>合并”,不需要合并的时候就不合并,一点问题都不会有,尤其是多版本同时维护的时候,cherry-pick取代merge是常态
不过git的master确实有点混淆,不同的项目的策略不一样,有的master是stable的含义,里面是稳定版本,新版本在分支里,有的反过来master是dev的含义,稳定版本在分支里。还有的master是release的含义,里面是“保持和线上部署一致的那份代码”。 所以我觉得可能直接不用master,用更明确的分支名称有可能是个更好的策略?
我认为你描述的场景下,不同的版本在不同的分支下或者不同的项目下基本是一样的,因为不同分支之间基本不会合并了(分支叫什么名字可以不用太过在意)。那么在一个改动如果需要应用到不同版本时,我觉得可以考虑如下的方法:
- 可以采用git submodule管理模块,改动时直接修改submodule对应的hash即可。
- 在采用多分支管理时
- 用git cherry-pick的合并一个commit过来
- 用git checkout直接把单独的文件拿过来
- 在采用多项目管理时,可以用git archive把相关文件弄过来
-
我们开发的产品就是典型的多分支并行,已经持续运行2年+,没有存在明显的问题;大致介绍下几个关键点,有更好的方案可以一起交流
- 每个发布的分支命名规范为版本号,类似
1.0
2.0
3.0
- 新功能开发从
master
拉分支开发,或者直接在master
上开发;测试通过后从master
分支上拉新版本分支,如4.0
- 版本分支上遇到bug需要修复时,需要合并后面的版本分支以及
master
分支 - 为了减少维护工作量,只维护最近的3个版本分支(低版本最终还是需要升级到新版本,只是存在时间差)
- 每个发布的分支命名规范为版本号,类似