怎么管理分支是每个研发团队都会比较关心的问题,好的管理模式可以帮助我们提高效率减少问题,相反如果分支模型和业务不太匹配,那么可能给大家带来的将是无尽的伤痛。 下面介绍下几个比较出名的分支模型,我们可以选择直接按照某个模型实施,也可以在其上进行适当的调整来更好的匹配我们的业务场景。
1、GitFlow分支模型
该分支模型于2010年提出,出现的时间相对较早,名气比较大,但现在大部分人都认为它不太适合真实的开发场景,其严格的流程也加剧了复杂性。在开发人员较多,分支多的情况下,以及面对当前的持续集成来讲,都不是很友好。
虽然不太推荐了,但大家还是可以了解下。
分支 | 说明 |
master | 生产分支。该分支只能从其他分支合并,且都是可直接发布到生产环境的代码 |
develop | 主开发分支。包含所有要发布到release的代码,由feature分支合并而来。 |
feature | 功能分支。从develop分支创建。 |
release | 发布分支。基于develop分支创建,测试并修复bug后合并回master和develop |
hotfix | 补丁分支。基于master分支创建,完后合并回master和develop分支 |
规则和约定:
1)初始时通过git init初始化仓库并创建默认的master分支
2)接着从master分支创建develop分支
3)从develop分支创建feature分支
4)feature分支开发完成后合并回develop分支
feature分支上本地进行单元测试
5)当想要发布时,从develop分支创建release分支,待测试完成后将其合并回master和develop分支
develop分支可用于SIT(test)环境,release分支可用于UAT环境;
如果环境很多,是否还需要创建“环境分支”,例如用于压测的、安全测试的?
6)接着在master分支上打标签发布
直接用于发布到生产环境
7)生产环节出现bug,基于master分支创建hotfix分支,修复完成后,合并回develop和master分支,且master分支上继续打标签
在该模型中,develop作为主开发分支,所有开发人员的代码都会被陆续的合并到该分支上。等到大家都合并完成且测试人员测试通过后,就要开始考虑要发布代码了,这时就从develop中创建release分支来应对这次发布的工作,最后验证符合发表条件后合并回master以及develop,同时在master分支打上版本tag用于发布到生产环境。
该模型要求master分支上的代码非常稳定,可随时用于生产环境;其流程还有点像按照“单元测试”-> "集成测试" -> "用户验收测试" -> “产品发布” 的逻辑向前推进;
2、TrunkBased分支模型
该模型于2013年提出,该模型基于主干的开发方式。基于主干的开发是指所有开发人员将源代码提交到一个共享分支。发现的bug在主干上修复并合并到发布分支,而不是在发布分支上修复并合并到主干。
分支 | 说明 |
主干 | 所有开发和测试都在该分支上进行,一般命名为“trunk”、“master”、“baseline”等 |
feature | 功能分支,开发完成后合并回trunk分支 |
release | 只用于发布,不在上面做任何修改【每次大版本都拉个新的版本分支】 |
对于小团队,可以不要feature分支,直接在主干分支开发即可
对于大团队,创建feature分支开发,开发并完成后合并回trunk分支
3、GithubFlow 分支模型
该模型于2011年提出。我在查阅资料的时候,发现了两个版本的说法,一个版本是部署是在分支合并之后,另一个版本是部署在分支合并之前。总的来说就是“部署”的时机可以灵活选择。
规则和约定:
1)主分支中的任何内容都是可部署,且更新应该与发布的产品是一致的
2)要处理新东西时,从主分支创建对应的分支
3)本地开发提交,并定期的将代码提交到远程的同名分支下
4)当你认为该分支已经准备好与主分支合并了,发起Pull Request请求
5)其他人审阅你的代码,如果有问题会给你提出修改建议等
6)如果审阅通过则进行代码的合并与部署
7)删除新建的分支
特点:
- 模型简单(单分支),适合持续部署(合并就部署)
- 不区分功能分支或补丁分支
思考:
- 功能分支可能被创建多个,每个分支都会发起与主分支合并的Pull Request请求,并且在通过审阅后便会进行合并和部署。难道每个合并都会部署?这样的部署是否会导致功能不完整?
- 多个环境的部署如何实施?
4、GitlabFlow分支模型
该分支模型于2014年提出,它吸取了Git flow 与 Github flow的优点,既有适应不同开发环境的弹性,又有单一主分支的简单和便利。
GitLab工作流的11条规则
- 使用特性分支,不要在master上直接提交
- 测试所有提交,而不仅仅是master上的提交
- 在所有提交上运行所有测试(如果测试运行时间超过5分钟,让它们并行运行)
- 在合并到master之前执行代码审查,而不是之后
- 部署是自动的,基于分支或标记:如果您不想每次都部署master,您可以创建一个产品
- 标签由用户设置,而不是由CI设置
- 版本是基于标签的
- 推送(push)的提交永远不会重基(rebased):代码应该干净,历史也应该干净
- 每个人都从master出发,以master为目标
- 先修复master中的bug,然后再修复发布分支
- 提交消息反映意图
原文:the-eleven-rules-of-gitlab-flow
规则和约定:
1)要处理新东西时,从主分支创建对应的分支
2)本地开发提交,并定期的将代码提交到远程的同名分支下
3)当你认为该分支已经准备好与主分支合并了,发起Merge Request请求
4)其他人审阅你的代码,如果有问题会给你提出修改建议等
6)如果审阅通过则进行代码的合并
7)master分支合并后,自动CI/CD到dev环境进行测试
8)如果发现问题,则创建分支进行修复【即回到第1步】
9)测通过后,创建从master到pre-production分支的Merge Request请求
10)创建从pre-production分支到production分支的合并请求来上线发布
11)需要发布版本时,从master分支指定提交创建相应发布版本
对于发现的bug,一般的逻辑都是在原有从master上创建的分支中修改(如果没被删除),然后发起到master的合并请求;如果该分支已经被删除,可从master创建用于修复bug的分支; 然后master分支测试没问题后,再通过cherry-pick的方式合并到pre-production;待pre-production测试也通过后再合并到production。
特点:
- 不要求主分支中的任何内容都是可部署
- 增加环境分支来应对多环境持续部署的场景
- 添加发布分支来应对多版本发布的场景
5、OneFlow分支模型
该模型于2017年提出。OneFlow 旨在成为 GitFlow 的直接替代品。作者认为:维护一个长期存在的分支可以大大简化版本方案和开发人员必须执行的日常操作。它还使项目历史记录更清晰、更易读,从而更有用。
整体逻辑:
1)只有一个永恒的分支(主分支),master,default,current,mainline
2)功能分支从master分来,开发完成后要合并会master
3)创建发布分支release
4)从发布分支再合并回master分支并打tag
特点:
- 对持续集成场景不太合适
- 玩法可以很多,核心点在于有一个永恒的分支
- 但其灵活性也会带来实施的复杂性
6、AoneFlow分支模型
AoneFlow结合了TrunkBased和GitFlow的优点,同时引入了新的自动化和分支管理工具,以确保及时发布高质量的软件产品。
三条基本规则
- 开始工作前,从主干创建特性分支
当一个新作业开始时(例如创建一个新功能或解决一个错误),就创建特性分支。
- 通过合并特性分支,形成发布分支
- 发布到在线正式环境后,将相应的发布分支合并到主干中,给主干添加标签,并删除与该发布分支相关联的特性分支
小结
在研发过程中,我们都会类似的场景
- 仓库的初次创建
- 开发新功能
- 部署到测试环境
- 修改测试中的bug
- 部署到生产环境
- 修改在线的bug
- 产品发行版发布
对于toB场景,还可能存在
- 每个发行版都有多个客户使用
- 每个客户都有定制化需求
- 客户使用过程中都可能发现bug
思路
- 最好只有一个不可删除的主干分支,避免操作复杂
- 主干分支最好保持稳定,可随时被发布
- 临时分支可根据需求而创建(例如特性分支、环境分支、发行版分支等)
- 临时分支何时删除可根据需要决定
- 代码审查考虑在发布前进行
- 一个统一的分支命名规范
- 提供给客户的发行版fork出自己的仓库
- 所谓打补丁,就是替换修改后的文件(至于如何替换方法很多)
明确几点
- 主干分支,不像特性分支等具有某种特殊含义,其包容万象,只负责记录你的代码提交。所以它可以只记录和发布对应的提交,也可以记录特性分支合并的提交、修改bug合并后的提交,甚至你都可以不开其他临时分支,都在主干分支上提交皆可。
- 创建发布分支,表示要使用该分支进行发布操作,发布完后其职责就结束了,可选择保留也可选择删除,但删除前别忘了合并会主干分支
- 在持续集成与发布中,往配置的分支上提交代码就会自动触发流程,包括:代码扫描、编译、打包、构建镜像、提交到镜像仓库、部署到对应环境等一系列操作
对于一些既没有持续集成,也没有多套环境的团队来说,一个主干分支+特性分支就可以满足了,而且还简单;如果有多个客户,给每个客户fork一个仓库即可。
对于具备持续集成和多环境的团队,一个主干分支+特性分支+环境分支也基本可以满足。
附:master分支改名了
最近我部署了一个10.0版本的SonarQube,在设置“非活动时要保留的分支”的时候,发现默认的分支名变成了“main”,而以前都是“master”。于此同时我发现Gitlab也是将默认的分支名从“master”改成了“main”,感觉“master”大家都用的很习惯了,怎么突然就改了呢?
原来这一切都来源与西方的“种族歧视”。事情源自2020年5月25日,一名白人警察“德里克·肖万“用膝盖压在黑人”乔治·弗洛伊德“脖子上9分29秒,最终致其死亡的事件,该案件也被称为:美国弗洛伊德被“跪杀”案
随后黑人团体们就组织了”黑人的命也是命”(Black Lives Matter)的抗议活动,然后“master(主人)”、“slave(奴隶)”、“blacklist(黑名单)”、“whitelist(白名单)”等词汇就遭殃了,这些词汇竟成了带有种族性的非包容性术语。好吧,我想说单词的命也是命啊,种族歧视不是靠这种方法就能去除掉的。