共计 6378 个字符,预计需要花费 16 分钟才能阅读完成。
简介: 编写代码,是软件开发交付过程的终点,公布上线,是开发工作实现的起点。代码分支模式贯通了开发、集成和公布的整个过程,是工程师们最亲切的小伙伴。那如何依据本身的业务特点和团队规模来抉择适宜的分支模式呢?本文分享几种支流 Git 分支模式的流程及特点,并给出抉择倡议。
分支的目标是隔离,但多一个分支也意味着保护老本的减少。咱们能够别离从开发和公布分支的多寡,做个简略组合,即:
- 骨干开发,骨干公布。
- 分支开发,骨干公布。
- 骨干开发,分支公布。
- 分支开发,分支公布。
构想两个不同的场景:
- 如果一个软件,只有一个开发者,只须要一个公布版本,那他须要什么样的分支模式?
- 如果一个软件,有 10 位开发者,须要反对多个版本,那他们又须要什么样的分支模式?
一个好的分支模式,能够大大提高软件的开发、集成和公布效率。抉择什么样的分支策略,是每一个开发团队开始工作时面临的第一个问题。那么,抉择什么样的分支模式才适宜咱们呢?在答复这个题之前,咱们先理解一下几种常见的分支模式。
支流的分支模式
常见的分支模式有 TBD(即骨干开发模式)、Git-Flow 模式、Github-Flow 模式及 Gitlab-Flow 模式。
TBD(骨干开发模式)
即所有开发者,仅在一个开发分支(即骨干)上进行合作开发的模式,在这种模式下,不容许新建任何长期存在的开发分支,有且仅保留骨干分支进行开发合作。
因为没有长期拆散的其余开发分支,任何代码变更继续地更新到骨干上,在肯定水平上防止了 merge 代码带来的困扰。同时,在这种开发模式下,倡议采纳公布分支的策略,依据软件版本的公布节奏拉出公布分支。在 TBD 模式下,所有的批改都是在骨干上,哪怕是缺点的批改也是,批改完缺点后,再 cherry pick 到公布分支上。
其特点总结一下就是:
- 有且仅有一个开发分支,即骨干分支。
- 所有改变都产生在骨干分支。
- 公布能够从骨干拉公布分支。
- 骨干上进行的修复须要依据缺点的修复策略,确定是否 cherry pick 到对应版本的公布分支。
因为团队共享一个开发分支,并且在开发分支上进行集成验证,而每次代码提交都会触发集成验证,这就要求每次代码的变更在骨干上都能疾速地验证,以确定是否承受下一次代码变更(每次代码变更都应该基于前一个稳固的版本进行),为了保障骨干始终处在可工作状态,这就须要:
- 每一次的变更要小,这样在验证的过程中能力管制范畴。
- 疾速实现验证,这就要求有绝对欠缺的自动化查看验证机制。
所以,骨干开发模式能够说是继续集成的要害推动者。骨干开发模式十分利于继续集成,并且依据稳固和骨干基线,做到随时公布,以达到继续交付。但这些是建设在团队成熟的合作能力和绝对成熟的工程配套的根底上,疾速地对骨干的变更提交实现编译、查看及验证;同时,因为采取公布分支的实际形式,在产品版本、分支、部署场景的对应关系须要梳理分明,防止公布分支凌乱,及缺点批改在各分支上的修复策略。
因为骨干开发要求每次变更提交都要小,并且要疾速验证完,保障骨干是处在可公布状态。对于一些处在开发过程中的个性,如每次变更提交,并非意味着残缺个性的实现,为了隔离“个性半成品”对骨干的影响,个别会采纳个性开关(Feature Toggle)的形式进行隔离。即频繁的代码变更提交,能够先做集成及验证,然而在公布的角度,通过(Feature Toggle)先暗藏相干个性,只有当个性都实现之后,才关上开关,个性齐全透出。
然而,个性开关的引入也并不是没有老本,因为个性开关是配置,实质上跟咱们经常用到的宏定义(#if #else)没啥区别,从实质上,它也是一种代码的分支。个性开关的应用,在肯定水平上让你的代码变得更软弱。所以,个性开关的应用,是建设在良好的代码设计根底上。
为了补救诸如个性开关这样针对某个个性开发的须要,而且当初软件开发中,越来越多的团队独特合作在一起实现某一个个性这样的场景,一种针对个性开发的分支模式就应运而生,这就是个性分支开发模式,最有代表性的就是 Git-Flow。
Git-Flow
Git-Flow 是为了解决多个不同个性之间并行开发须要的一种工作形式。当开始一个个性的开发工作的时候,从骨干上拉出一个个性分支,所有的对于该个性的开发工作都产生在这个个性分支上,当实现该个性的工作之后,再把个性分支合并回代码主门路上,并筹备公布。
Git-Flow 有以下几种分支:
- feature 分支:开发者进行性能开发的分支。
- develop 分支:对开发的性能进行集成的分支。
- release 分支:负责版本公布的分支。
- hotfix 分支:对线上缺点进行批改工作的分支。
- master:保留最新已公布版本基线的分支。
每个个性都有属于本人的开发分支,即 feature 分支,当一个开发者须要在两个个性上进行工作的时候,他须要做的是通过 check out 命令在两个分支之间进行切换。这样做的目标是避免开发过程中,两个个性开发工作的互相烦扰。
个性开发过程中,须要针对该个性进行独自验证,当该个性并验证通过之后,merge 到一个叫做 develop 分支(大部分工夫与 master 分支相近)的集成分支中,对整个软件进行验证。develop 分支永远保留都是最近的未公布版本,当 develop 分支的代码被验证可公布之后,独自从 develop 分支拉出 release 分支进行公布。
当拉出 release 分支进行公布过程中,如果发现缺点,缺点的修复产生在 release 分支上,所做的缺点批改再继续同步到 develop 分支上。当 release 分支被公布完,其代码的最终版本会再次别离同步给 develop 分支和 master 骨干上。咱们能够发现,master 上永远保留的是可工作版本的基线。develop 分支保障的是开发集成中最新的版本。
Git-Flow 引入了一种叫做 hotfix 的分支,专门用于线上缺点的修复。当缺点修复完,再集成到 develop 分支,及同步到 master。其实,咱们能够了解 hotfix 是一种非凡的 feature 分支,只是它的变更提交在集成到 develop 分支的同时须要同步到 master。
是不是感觉这个模式很专(fu)业(zha)的样子,那咱们通过开发者做一个个性开发,按 happy path 捋捋:
- 开发者接到一个开发需要,从 develop 分支拉一个 feature 分支。
- 大家实现本人本地的开发工作,实现本地验证,提交代码到 feature 分支。
- 基于 feature 分支进行验证,并继续合并新的开发代码。
- 实现个性的开发,并且 feature 分支验证无误,将 feature 分支的代码合并到 develop 分支。
- 在 develop 分支进行集成验证(此处,可能和其余合并进来的个性分支一起进行验证),集成验证结束,feature 分支会被删除。
- 当 develop 分支是一个成熟的公布版本时,如实现了彻底的测试及问题的修复,拉出 release 分支进行公布。
- 实现公布之后,将 release 分支合并入 develop 和 master(master 保留的永远都是已公布的最新代码),并删除 release 分支。
Hotfix 的流程如下:
- 如果公布之后,发现了缺点,基于 master 拉出一个 hotfix 分支。
- 在 hotfix 对问题进行批改及验证。
- 问题的修复合并到 develop 和 master 上。
- 删除 hotfix 分支。
Git-Flow 的分支模式,提供了绝对齐备的各种分支,以笼罩软件开发过程中的大部分场景,以致于在相当长的一段时间内,人们认为这就是规范的 Git 的分支模式(因为从它的名字上看,也很容易产生这样的幻觉)。然而,Git-Flow 也存在着显著的一些问题,如:
- 分支特地多,而且每类分支都有特定限定的用法,开发者很难记住什么分支是干什么的。
- 整个分支模式过于简单,大大超出大部分团队和我的项目的需要。
- feature 分支的生命周期过长导致的合并抵触。如果一个个性所在 feature 分支生命周期过长,它跟 develop 分支的差别就越大,这样,在该个性集成到 develop 的过程中,潜在的代码抵触将是集成的噩梦。
- 像 develop 分支,感觉其实存在的意义不是太大,齐全通过 master 就能够代替集成的作用,额定为变更提交的集成引入 develop 分支,对分支模式来说,变得更加的简单;同样,如果勾销 develop 分支,那么,hotfix 分支存在的意义也就没有必要了,因为这个时候,hotfix 分支与 feature 分支就没有任何的差异。
那么,有没有一种分支模式,既蕴含开发工作对于主线的隔离,又绝对 Git-Flow 轻量一点?我认为,真正的解决方案,应该是实质极简略的。这里,咱们就不得不给大家介绍另一种分支模式,叫做 GitHub-Flow。
GitHub-Flow
在 GitHub-Flow 上,第一步就是没有 Git-Flow 中所介绍的 release 分支。对于 GitHub-Flow 来说,公布应该是继续地,当一个版本筹备好,它就能够被部署。同样,在 hotfix 上的解决,GitHub-Flow 认为,hotfix 与那些小的个性批改没有任何区别,它的解决形式也应该与之类似。
在 GitHub-Flow 的整体流程是:
- 在 master 分支上的所有代码都应该是最新可部署、可工作的版本。
- 如果要进行新的工作,从 master 分支上拉出一个新的分支,并以工作工作清晰命名,如“new-scheduling-strategy”。
- 尽可能频繁地提交代码变更到本地分支,与此同时,尽可能频繁地同步到服务端雷同分支名的分支。
- 当筹备合并代码到 master 骨干分支上,通过发动 Pull Request,提请代码评审。
- 通过代码评审后,或与此同时,须要将该分支部署到测试环境,进行验证。
- 如果评审通过及验证通过,代码则合并到 master 骨干分支上,应该立刻部署到生产环境。
GitHub-Flow 相比 Git-Flow 来说,有个不言而喻的益处——简略。另一个益处就是继续部署的要求,尽可能疾速地发现 master 分支的问题,并能通过 rollback 等机制,疾速复原。将所有内容合到 master 分支中,并常常部署,意味着你能够最小化未公布的代码量,这也是精益开发和继续交付所提倡的最佳实际。部署本来是一件很繁琐的事件,然而因为要频繁做,咱们就容易把这样一件事件做简略,以达到继续交付的目标。
尽管 GitHub-Flow 简化了 Git-Flow 的分支模式,然而对于部署、环境、以及公布,该分支模式依然存在许多未答复的问题,所以,咱们心愿通过 GitLab-Flow 来为这些问题提供更多的参考。
GitLab-Flow
GitLab-Flow 相比于 GitHub-Flow 来说,在开发侧的区别不大,只是将 pull request 改成了 merge request,而 merge request 的用法与 pull request 相似,都能够做为代码评审、获取反馈意见的一种沟通形式。
最大的区别体现在公布侧,即引入了对应生产环境的 production 分支和对应预发环境的 pre-production 分支(如果有预发环境的话)。这样,master 分支反映的是部署在集成环境上的代码,pre-production 分支反映的是部署在预发环境的代码,production 分支反映的最新部署在生产环境的代码。
当一个个性开发实现,提交 merge request,将个性开发的代码合并到 master,并部署到集成环境进行验证;当验证通过之后,提交 merge reqeust,合并 master 到 pre-production 分支,并部署到预发环境,进行预发环境上验证;当预发环境验证胜利之后,再提交 merge request,将 pre-production 分支上的代码合并到 production 分支上。
除了以上这种按环境,将骨干公布向上游合并,并顺次部署公布的过程。GitLab-Flow 同样反对不同版本的公布分支,即不同的版本会从 master 上拉出公布分支,不同的公布分支再走 pre-production 分支和 production 分支的形式进行公布。
从下面的介绍中,咱们发现,GitLab-Flow 更多是在公布侧做了更多的工作。同样 GitLab-Flow 因为跟 GitLab 工具强依赖,所以 GitLab-Flow 与 GitLab 中的 Issue 零碎也有很好的集成,在其举荐的工作模式中,每次新建一个新的 feature 分支,都是从一个 issue 上发动的,即建设 issue 与 feature 开发分支之间的映射。
pros vs cons
所以,如果咱们还是依照开发和公布的分支多寡来分类的话,以上这些分支模式别离属于:
- TBD 应该是骨干开发,能够是分支公布,也能够是骨干公布。
- Git-Flow 应该是分支开发,分支公布。
- GitHub-Flow 应该是分支开发,骨干公布。
- GitLab-Flow 反对分支开发,但反对骨干公布,也反对分支公布。
理解了常见的这些分支模式之后,咱们在工作中就能够依据本身的业务特点和团队规模来抉择适宜的实际,没有相对好的模式,只有适宜的模式。
依据团队本身和我的项目的特点来抉择最适宜的分支实际应该从哪些地方考量呢?
抉择适合的实际
首先是我的项目的版本公布周期。如果公布周期较长,则 Git-Flow 是最好的抉择。Git-Flow 能够很好地解决新性能开发、版本公布、生产系统维护等问题;如果公布周期较短,则 TBD 和 GitHub-Flow 都是不错的抉择。GitHub-flow 的特色在于集成了 pull request 和代码审查。如果我的项目曾经应用 GitHub,则 GitHub-Flow 是最佳的抉择。GitHub-Flow 和 TBD 对继续集成和自动化测试等基础设施有比拟高的要求。如果相干的基础设施不欠缺,则不倡议应用。
另外,从须要公布版本的多寡的角度来看:
- 反对一个产品多个公布版本,用 Git-Flow。
- 反对一个简略产品单个公布版本,用 GitHub-Flow 或 TBD。
- 反对一个简单产品单个公布版本,用 GitLab-Flow。
如果发现,现有支流的分支模式都无奈满足你的要求,那么,咱们能够定义本人的分支模式,如咱们有个团队是基于骨干开发的,于是定义了春夏秋冬分支模式,春天用“春分支”,夏天用“夏分支”……,我集体就蛮喜爱的,起因有二,一是做到了骨干开发,继续公布,二是名字起得很有意思,开发工作肯定要有乐趣,不是么?
参考
[1]TBD: https://trunkbaseddevelopment.com/
[2]A successful Git branching model:
https://nvie.com/posts/a-successful-git-branching-model/
[3]Learn Version Control with Git:
https://www.git-tower.com/learn/git/ebook/cn/command-line/advanced-topics/git-flow
[4]Branching Models and Best Practices for Abstract – Design Version Control:
https://projekt202.com/blog/2018/branching-models-and-abstract
[5]Understand the GitHub-Flow:
https://guides.github.com/introduction/flow/
[6]GitHub Flow:
http://scottchacon.com/2011/08/31/github-flow.html
[7]Introduction to GitLabFlow:
https://docs.gitlab.com/ee/workflow/gitlab_flow.html