这篇文章分享 Git 分支管理以及一些日常情况处理方案,目的是设立 Git 规范让项目 Git 操作一眼明了,也为大家在处理异常时提供一些方案。
分支管理策略是一个见仁见智的问题,没有绝对最好的,只有最适合自己项目的。
并且规则是灵活的,可以根据不同的项目来做衍生的规范。
分支命名
分支的命名基于以下的准则:
- 一眼明了
- 减少生命消耗
基于上面的两个准则设计的分支命名如下:
| 分支 | 名称 |
|---|---|
| master | 主分支 |
| releae-* | 预发布分支 |
| fix-* | 紧急修复分支 |
| pm-* | 产品需求分支 project manager 缩写 |
| pd-* | 技术需求分支 project developer 缩写 |
master 分支
master为主分支,用于部署到正式环境。并且master分支是被分支保护的,只能merge request合并,经过项目负责人review才能合并;
release 分支
release为预发布分支,用于部署到预发布环境;release分支从master切出,合并需求分支;
如果release分支测试出问题,建议在需求分支上修改验证后,再合并到release分支;
fix 分支
fix 分支为修复分支,不采用业内常用的hotfix命名,是因为fix命名也可直观并且节省时间;
fix分支从master切出,merge 到 master 后删除源分支
pm pd 分支
pm,pd分支为开发分支,有业内feature分支延伸,不要问为何不用feature命名,问就是因为节省时间,一眼明了;
pm,pd分支都是从master分支上切出,用于部署开发,测试环境;
其他
分支命名仅能使用 .-_ 特殊符号;
因为当我们在做 CI或者webhook服务时,有可能会用到分支名来做文件夹等,为了避免系统文件夹不支持特殊符号导致出错,所以限定可以使用的符号;
不建议用 / 符号的原因是因为,在linux中/代表着路径,如果存在使用分支名创建文件夹的时候会导致创建二级目录;并且在webhook中传给钩子服务中的分支命名是 repo/projectName/branchName,如此不能确认repo/projectName不是固定的情况下,会导致分支名取错;
公司项目的分支命名
前面也说到要找到一个适合自己的分支管理;在公司的一个项目中,有自己的一套分支管理;
这项目是有其特殊性的,具体表现在多业务项目多版本的集合在一起,需求分域名提测;
简单提一句之所以做需求分域名提测,是因为当测试环境只有一个的时候,需要排队使用测试环境的测试;
针对这种多业务多版本的开发,我们可以在分支命名的规范上再做修改,分支命名为:
| 分支名 | 备注 |
|---|---|
| master | 主分支 |
| pm-project-version-feature | 产品需求分支 |
| pd-feature-date | 技术需求分支 |
| fix-* | 修复分支 |
产品需求分支 我们加了 project 的区分,project 命名尽量使用缩写,减少生命消耗,如腾讯项目1.1版本微信功能,我们可以起个名字 pm-tx-1.1-wechat;
同时这个项目是没有release分支的,主要是因为该项目有钩子服务帮忙在机器上,部署nginx服务;

如此,我们仅需要在项目中nginx配置文件中配置好各环境接口地址,部署到机器上,即可同时将一份代码同时应用到不同环境,即时后端没有部署预发布环境等;
FAQ
1. 代码被回滚后如何操作
通常会有的情况是代码被merge上线之后发现有问题,解决的问题的最快方法是在业务机器上回滚代码;
如果我们不是使用发release包的方式部署代码,并且仓库master有CI自动部署的操作,最快的方式是回滚master代码;
gitlab上代码被merge之后是有提供一键回滚操作的,使用的是revert,revert表示用一次新的提交重做某次提交,如下例子1表示revert操作后的结果;
例子1:
master a -- b c -- d(revert c)
\ |
dev-c b -- c
理想情况下,当我们排查好问题后,会在原来的开发分支或者新建一个修复分支修改对应代码后,再pull request master;
但是我们会发现,无论从master切新的分支进行修复,或者更新 master 到 dev-c 分支(不更新会有冲突),都会发现c的代码都被回滚了,那么如何把c的代码再加入到工作区呢?
我们只需要在开发分支中,把 master 的回滚操作再回滚,就可以得到c的代码了
revert操作结果如下:
master a -- b c -- d(revert c) -- e
\ | \ |
dev-c b -- c d(c 的代码没有了) -- e(revert d后得到c代码 && fix something)
具体操作为
git checkout dev-c
git merge master
git revert -n commitID // 回滚回滚操作,并且不提交
git add .
git commit -m 'xxxx'
git push orign dev-c
当然回滚的还有其他方法,这里只介绍常规的做法;
PS: 用reset方法是不行的,这是另一个话题了;
2. 多人开发同一版本如何进行分支管理
在多人同时开发的统一的版本中,会出现同时开发A、B、C等多个需求,并且要求需求同时上线;
因为是用一天上线,开发人员可能会乖乖地给这些需求建一个统一的分支1.0.0,然后把所有的需求代码都提交到这个分支上;
但是现实是到了发版的日子,已经通过测试的需求,会出现种种情况:
- 比如B需求不上线了,这么就要把B需求相关的代码注释,需求改动小还好说,需求大涉及的代码块太多,耗时耗力后果不堪设想;
- 又或者A、B、C需求同时上线了,B要回滚,那么就只能把
1.0.0分支都回滚,然后再注释,再上线...
如果测试和发版不是同一个release包,那么操作操作已经测试通过的代码,是危险的操作
为了避免上面种种情况,我们是建议每个需求都分配不同的分支,如 pm-1.0-a,pm-1.0-b,pm-1.0-c。

这样做的好处是我们每个需求都可以自由地组合,比如上面的B需求不上线,我们可以把a,c的需求合到1.0.0分支,避免操作代码,更加灵活组合;