Git Flow 分支模型
Git Flow的主要特点是有两个长期分支和三个临时分支。
长期分支:Master,develop
Master分支:用于保持与生产环境一致或者半步先于生产环境,保证生产环境的实时可用。
develop:开发的集成分支,主要用于显示最新的开发状况。
临时分支:feature,release,hotfix
feature:新功能特性分支,与develop合并
hotfix:生产环境对应的bug分支,与Master、develop合并。
release:发布实施分支,功能开发完成提交测试的分支,与master合并。
命令:
创建分支特性:git checkout -b 特性分支名称 develop
进行特性内容开发直至可以提交:git add 文件名 ;git commit -m "开发内容注释信息"。
特性分支开发完成后切换至develop分支:git checkout develop
合并特性分支开发内容到develop分支:git merge --no-ff "特性分支名称"
删除特性分支:git branch -d “特性分支名称”
将修改的内容推送到远端仓库保存:git push origin develop
分支规范:
源分支:特性分支需以develop分支为源分支。
目标分支:特性分支的合并目标分支为develop分支,此模型只能合并到develo分支。
分支命名规则:master/develop/hotfix-*/release-*命名所有分支
样例:
创建项目:curl --request POST --header "PRIVATE-TOKEN: 密匙" --data "name=gitflowmodel" "http://xxx:xx/api/v4/projects" |jq
初始化Master分支:git clone http://xxx:xx/api/v4/projects.git
在Master分支添加文件:touch C1
提交Master分支:git add C1;git commit -m "add C1"
初始化develop分支:git checkout -b develop master
至此,两条长期分支(master分支和develop分支)已经就绪,接下来我们开始模拟实际的分支开发、Bug应对、release等临时分支操作。
feature特性分支:
创建特性分支:git checkout -b feature_F1001 develop
特性分支新建文件夹:touch C3 ;git commit -m "add C3"
切换至develop分支:git checkout develop
特性分支合并到develop分支:git merge --no-ff feature_F1001
删除特性分支:git branch -d feature_F1001
推送至远端仓库:git push origin develop
release分支:
hotfix分支:
经验总结:
1.实践经验:对master分支进行保护
master 分支保持着软件可以正常运行的状态,一般不允许开发者直接对master分支的代码进行修改和提交。结合GitLab的具体方式,可以将master分支设定为protect方式。
2.实践经验:对master分支进行权限管理
master分支由专人管理,结合GitLab的权限管理,设定团队负责发布的人具有owner或者master的权限,其他人禁止直接对此分支进行操作。
3.实践经验:结合自动化测试,建立高效的反馈机制
建议在项目中添加自动化测试环节,使用GitLab的webhook设定,在进行merge操作时有的项目需要自动运行自动化测试验收,如果不通过及时报警,此自动化测试即使覆盖率很低,也能避免大部分人为因素导致的问题,比如不小心将一个编译都没有通过的版本推到了 master分支上,即使有专人负责,专人也并不一定对所有的技术、项目功能及实时状态都进行了全面的掌控,另外如果所有的问题都需要人工检查和确认,那么会产生一个会无限增长的checklist,最终会形成一个几千甚至更多行的、谁都不会去看的敷衍了事的 checklist,其在很多项目实践中已经得到了证实:只在事后检讨的时候有用,检讨之后这个checklist会变得更长。
4.实践经验:规范合并前的基础原则
develop 分支是开发过程中代码的中心分支,与 master 分支一样,这个分支也是非常重要的分支,可能每个人都会参与这个分支的合并操作,所以,合并之前需要建立基础的原则,比如Java的项目最好符合如下条件再合并到本分支。
● 通过本地编译。
● 本地本次修改内容没有新的SonarQube高级别的缺陷对应。
● 通过本地单元测试。
● 通过手工或者自动化验收的测试。
5.实践经验:结合持续构建保证流水线不中断
develop分支进行传统的每日构建甚至实时构建,结合不断完善的自动化测试,以可以接受的成本和代价保证开发的流水线不会中断。
6.实践经验:设立时间限制
设立时限原则:develop分支构建或者关联的自动化测试一旦出现问题,就要结合工具第一时间定位到对应的负责人,并进行回滚或者紧急修正,根据项目集成情况设立时限。例如,平均每日由各个临时分支提交的功能频次为4次,则意味着各个分支在每天8小时的工作时间内,平均每2小时(8小时/4)会有一次提交。如果提交之后发生问题,在2个小时内还没有得到修正,则有较大概率出现有人需要在这个错误版本上进行提交的情况,所以可设立时限不超过 2小时。错上加错是最需要避免的,发现问题应在第一时间解决,若超过时限,应立即止损回滚。7.实践经验:分支的合并应该考虑到回滚的便利
特性分支合并或者其他的分支合并,应尽可能不使用fast forward的方式,以方便回滚和状态确认。
8.实践经验:妥善管理临时分支
特性分支在Git Flow中仍然是临时性分支,使用之后需要删除此分支,同时删除远程仓库中的该分支。另外,分支的增多意味着可能的沟通、合并、冲突等的增加,而这些正是精益开发中所要规避的“浪费”,不用即删,因为在实践中我们已经利用了Git的非fast forward的方式,所以特性分支开发的信息已经完整地在 develop 分支中进行了保存,删除特性分支不会引起问题追踪上的问题。
9.实践经验:规范特性分支合并操作
特性分支或者其他分支合并到开发主分支(develop分支)的策略需要项目根据情况自行创建,最主要的原则为尽量避免发布时期不同导致的频繁的分支合并、版本挑选等手工作业。例如,发布计划明明是最后的任务,但是在项目已开始的时候就合并进了主分支,这样会导致后续每次发布的时候都需要将此内容挑选出去,虽然使用GitLab的rebase+cherry pick等功能可以实现这种要求,但是在提交的规范中明确要求可以避免这种麻烦。
10.实践经验:规避单次大规模功能的修改提交
release分支主要用于大型项目中各个特性分支开发完毕之后,定义一个准备就绪到工作完成的中间阶段,一般会和项目的管理工作结合进行,比如进行发布的申请和批准、结果确认和审核。
不同的开发流程不仅需要考虑技术本身,还需要考虑各个公司实际的流程规范、审查要求等,以保证发布能够正常进行,虽然可以在release分支上进行少量的修改,但是大规模的功能修改应尽可能地规避。
11.实践经验:开发中加强签名的使用
为了避免提交或者 tag 信息被恶意修改,可以使用签名技术。签名使得操作具有了不可抵赖性和无法篡改性两重保证,而这两重保证在Git中只加入-u或者-s选项即可实现。
12.实践经验:增强hotfix分支和release分支操作的规范性
hotfix分支和release分支上的对应需要对Git Flow的两条分支(master分支与develop分支)主线同时进行更新,一旦忘记其中一条,往往会引起不必要的后续问题。hotfix 分支出现的场景一般是紧急的故障修复,在实际情况中被忘记更新的一般是 develop 分支,也就是说故障修复的内容在master分支进行了更新,却没有在develop分支进行更新。这将会导致使用此develop分支在下一次进行发布的时候,会覆盖掉此前hotfix分支修改的内容,从而使生产环境中已经修复的故障再次出现,所以在流程规范或者工具的自动化里面建议增加对此操作执行的确认,以免忘记更新。
13.实践经验:GitHub Flow使用规范
GitHub Flow在使用时建议遵循如下规范和原则。
● 只有可以部署的内容才会放到master分支上,所以master分支上的任何内容都是可部署的。
● 特性分支的创建需要以 master 分支为基础,同时特性分支的命名需要意义清晰、容易理解。
● 特性分支需要经常更新到远程仓库中,远程仓库中的特性分支应与本地特性分支名称相同。
● 当需要反馈或者帮助的时候,或者当分支已经可以进行合并的时候,随时可以开启一个Pull Request。
● 仅当Pull Request通过发布之后才进行合并。
● 内容被合并并推送到 master 分支之后,意味着此内容已经随时可以进行部署,根据持续集成的原则,应当立即进行部署。