Git 分支策略模型
本系列,是自己学习Linux过程中的笔记。
希望读者在看完全文后,也能留下你们的经验或者问题。
如果能从这里学到点东西,记得请我喝杯☕☕☕~
—— MinRam
在整理自己项目Polaris Technology Radar的分支策略时,采照了当前商用级分支策略,写了些个人对这种分支模式的理解。
如果产品是处于持续交付策略,那么可能更适合GitHub flow的策略,不要试图将Git硬塞入你的产品团队
同时分支策略不是唯一固定的,我们需要适配产品需求。对于IT,没有万能钥匙存在。
一、前言 Overview
本文章仅描述我自己项目中的分支策略和发布管理。当我们选择分支策略时候,应考虑产品的迭代模式,团队的开发规模和开发方式等方面。
以Polaris Technology Radar为例,该项目有如下几个信息:
- 项目开发团队人数 2~10人
- 项目代码规模小,满足单人开发条件
- 项目发布流程涉及多种环境部署
- 项目可能支持多个发布版本并存(正式版本/定制版本)
- 团队开发模式为功能特性独立
- …
二、为什么选择Git
Git作为一款版本控制系统VCS-Version Control System, 是开源项目不二的选择。让来自不同开发者的分支能够简单的对比/合并。
同样作为VCS的SVN- Apache Subversion, 没法连接数据库就没法工作,同时SVN只能满足在少量开发者的场景下进行版本管控。
三、主分支 Main Branches
受开发模式影响,整个项目存在两个永存的分支: release & develop.
3.1 Release Branches
我们认为release
为主分支,其中的代码始终满足发布状态,包含对下一版本要交付的功能特性代码。
该分支也是自动化构建的目标分支,只有该分支的代码,才会被发布到生产环境上。
3.2 Develop Branches
如名所示,develop
分支是处于开发测试中的代码。
只有当代码变动趋于稳定后并准备发布的时候,所有代码变动会以某种方式合并到release
分支中,并且标记版本号。
这一合并动作会在后面进一步详解。
所以,每次develop
的代码变更,合并到master
时,这就是一个针对生产环境的代码版本。
我们往往在这个合入动作(Pull Request)发生时,触发自动构建机制(DevOps, 如Git hook脚本)来构建我们的产品,并自动部署到生产环境上。
四、支持性分支 Supporting Branches
除了主分支(release & develop)的存在,依照我们开发模型,在整个分治策略中还有各种支持性分支,来协助团队成员进行并行开发,简化功能定位,以及为生产环境做准备。
有些分支也会协助开发者,快速修复实时生产环境上的问题。
与主分支的永久生命周期不一样,支持性分支的生命寿命是有限的,最终都会被删除。
对于这些支持性分支,大致包含以下几类:
- 功能性分支
- 发布性分支
- 热补丁分支
这些分支都有明确的特定目标,并且遵循一定的原则。如只能从哪些分支上分叉出来,只能合入哪些分支。
从Git的角度上看,这些分支没有任何区别,同样只是普通的代码分支,只是因为其目的特殊,所以有着特殊的含义。
4.1 特性分支 Feature Branches
- 根源分支:
develop
- 目标分支:
develop
- 分支命名规则: 一般以
feature-*
为命名规则,同时不包含release
,develop
和hotfix
字样
功能分支,用于为即将发布的版本开发新功能。在开发该功能特性时,我们无法预估该功能最终会在哪个版本进行发布。但对于功能分支来说,只要功能还在开发,分支就一直存在。
对于该分支,它生命周期的终点,要么功能开发完成,合并入develop
,准备发布。 要么因项目安排,功能被取消,最后直接删除分支。
功能分支,通常仅存在开发人员本地Git存储库中,不会存在远端代码仓库(origin)。
- 创建功能分支:
从develop
中创建。
1 | $ git checkout -b feature/hello-world develop |
- 完成功能开发,合并代码变动:
在实际代码管理中,往往需要提交Pull Request
,经过代码审查Review, 代码构建Build/Test来保证代码准确性。这里仅展示本地合并指令。
1 | $ git checkout develop |
--no-ff
该参数, 用来避免丢失特性开发分支的整个提交链信息,同时创建新的代码提交信息。具体详见Git fast forward merge内容。
以下为两者简单对比:
Pull Request
中也有同样的选项。
4.2 发布分支 Release-* Branches
- 根源分支:
develop
- 目标分支:
develop/release
- 分支命名规则:
release-*
release-* branches
是为下一版本的发布做准备。他是正式发布前的预先检查环节。不同于develop
分支对应的测试环境,release-
对应的环境,更符合生产环境的标准,且在release-
分支上只允许补丁相关的变动。
- 创建发布分支
release-*
是从develop
创建出来的。假设当前的生产版本为1.2, 而develop
已经完成新版本1.3所有的功能特性,我们就可以从develop
中分支出release-1.3
。
1 | $ git checkout release-1.3 develop |
接下来就是修改release-1.3
上的版本信息,比如配置上的版本号。这里用bump-version.sh
来自动更新这类信息。
release-*
分支会一直存活,直到合并到release
发布, 或者被删除.在此分支上,不得合入较大的功能变动。
- 完成发布分支
当release-1.3
已经满足发布条件后,我们需要将该分支合入release
中。同时我们需要在这次合入中打入特定标签,来保证我们能在后续众多的提交中,找到指定版本的发布提交点。
首先,需要更新release
的标签到新的版本号。
1 | $ git checkout release |
另外,为了保留release-*
的变动,我们还需要将release-*
合并到develop
,以保证所有的变动能在下一个版本中被包含。
1 | $ git checkout develop |
最后,就是永久性的删除该分支
1 | $ git branch -d release-1.3 |
4.2 热补丁分支 Hotfix Branches
- 根源分支:
release
- 目标分支:
develop/release
- 分支命名规则:
hotfix-*
热补丁分支同发布分支非常相似,同样为新生产版本做变动。不同的是,热补丁是计划外的。
在生产版本中总会出现一些关键Bug,需要立即采取措施来修复。我们就从生产版本的主分支分支出补丁分支来修复这类问题。
采取这样的策略,可以保证develop
分支上的开发团队可以继续专注于下一版本的特性开发。而由单独的团队来快速修复这一紧急问题。
- 补丁分支创建
热补丁分支是由release
分支出来的。例如生产环境出现了一个严重的Bug,但当前的develop
的功能并不稳定,这是我们就会从release
分支出hotfix branches
,然后在这条分支中开始修复致命问题。
1 | $ git check -b hotfix-1.0.1 release |
在创建出补丁分支后,不要忘了更新版本号,此处用bump-version.sh
代表这一动作。来描述该分支版本变化(1.0.0 --> 1.0.1
)。
接下来就是在这个分支上,修复所需要的Bug。
- 补丁分支完成
补丁分支的创建,需要合并到主分支release
。同时也需要合并入develop
分支,以确保该补丁能在下一个开发版本被修复。
此处为
release
,而不是release-*
。
首先,需要更新release
的标签到新的版本号。
1 | $ git checkout release |
下一步,就是将补丁合入develop
。
1 | $ git checkout develop |
如果当前存在release-*
分支,我们可以直接合入release-*
,而不用合并入develop
。
最后就是删除这一临时分支,及时清理无用分支,来保证整个仓库的简洁。
1 | $ git branch -d hotfix-1.0.1 |
五、总结 Summary
整个分支策略模型并没有什么新颖的技能点,但从分支管理角度,它反映整个产品的开发模型。为团队建立一个对开发和发布流程的共识。