Git 分支策略 Azure DevOps

最近在看git的集成,下面这个文章写的还不错,转载下:https://sunnycoding.cn/2019/03/23/git-flow-and-azure-devops/

本文结构

</nav>

想了很久,还是写这么一篇文章来总结一下有关分支策略和DevOps的一些内容吧。其实,DevOps相关的内容并不是我的工作范围,不过对于敏捷开发、DevOps、项目管理等等这一系列的与开发过程相关的内容,我还是有些经验的,也就抽时间跟大家分享一下吧。

Git Flow应该是很多基于Git分布式版本控制系统的项目所实践的一种开发流程,当然,很多人对于Github非常熟悉,甚至平时工作就是基于Github的。在此我也就不多介绍Git以及Github的概念了,只需要知道Github是基于Git的一个服务供应商,目前已被微软收购。Git Flow就是由Vincent Driessen基于Git这一版本控制系统所总结出来的一套可行的、能够满足很多项目开发需求(注意:不是大多数项目)的敏捷开发流程,英语水平好的朋友可以参考阅读Vincent的原文:《A successful Git branching model》。

Git Flow

Git Flow通常会用在有具体的release发布的概念的项目上,简言之就是类似于以前能够给客户提供安装包的项目,对于SaaS项目,Git Flow还是太重了,而且不同环境、多租户的部署策略也与Git Flow有一些差别。因此,团队还是应该根据自己的实际情况来选择合理的开发流程,这里所介绍的内容也是仅供参考。下图(来自《A successful Git branching model》一文)展示了Git Flow的整个流程,在这里,我会对这个流程做一个详细的介绍。

master分支

master分支始终保持了最近一次发布(release)的代码,通常情况下,通过tag的方式来标记每一次release。在Github中,每创建一次release,就可以基于某个分支(branch)创建一个tag。在tag被创建后,分支是可以删除的。因此,我觉得在上面的模型中,维护一个master分支并不是必需的。所以,有些团队为了直观,会将develop分支作为默认分支,甚至删除master分支。但我觉得删不删除也都无所谓,直接将master分支作为开发分支(也就是合并develop和master的职责)也是可以的。

develop分支与feature分支

develop分支(或者master分支),是项目开发的主要分支,它包含了项目的最新代码,开发和测试团队都会基于develop分支进行工作。每当有新的功能需要开发时,都会从develop分支分出一个feature分支。从实践的角度:

  • 上图中分主体功能的feature分支(Major feature for next release)以及后续版本的feature分支(Feature for future release),实际上,出现后续版本的feature分支的可能性不会太大,由于采用敏捷开发,团队通常不会做三个月以上的项目计划,因为没有意义,没有人能够确保三个月之内不会有功能需求的变更、backlog的调整以及市场对于项目本身的影响,因此,相对而言,近期的版本发布目标应该是比较明确的,长远的计划反倒显得意义不大。不过,也有可能会让团队的部分成员提前进入下一版本的研发,但由于敏捷开发和微服务理念的引入,一般敏捷团队也不会特别庞大,所以,这样的活动也不太会频繁发生。当然,还是应该依据项目实际情况而定,如果真有部分成员提前进入下一版本开发的需要,那就按上图中所描述的流程进行即可,不会有什么大问题
  • 多个feature并存的可能性还是很大的,团队的不同成员会工作在不同的feature分支上,当每个feature完成之后,都会合并到develop分支。合并过程可能会出现代码冲突
  • 每个成员是直接将代码提交到feature分支,还是自己再基于feature分支创建自己的工作分支?这取决于团队的代码审核(Code Review)流程,如果团队有严格的代码审核流程,开发人员应该在进行开发工作之前,基于feature分支创建自己的工作分支。开发完成后,将代码push到远程,然后提交Pull Request(PR)并邀请团队进行Code Review,Review通过,再将代码合并到feature分支,代码合并之后,将自己的工作分支删掉即可。如果代码审核流程不严格,那么直接将代码push到feature分支也是可以的,这需要团队成员建立起互信机制,并且有高度自治(Self-organize)的能力。这里有两点可以多写几句,首先不要觉得重复创建、删除分支会带来很大压力,Git的分支是非常轻量的,需要的时候就创建,不需要就删除,非常方便;其次,很多持续集成系统,对于多分支的开发流程以及Pull Request/Code Review流程都有完美的支持,Azure DevOps的这部分功能使用起来也是非常方便,之后我会详细介绍
  • 持续集成系统会从各feature分支上拉取代码进行编译,然后自动化部署到开发环境进行冒烟测试(Smoke Test),便于开发人员尽早验证已开发的功能。如果验证通过,开发团队可以将feature分支合并到develop分支,并删除feature分支,然后进行下一个feature的开发
  • 持续集成系统会从develop分支上拉取代码进行编译,然后自动化部署到测试环境供测试团队(QA)进行测试,最后给Product Owner或者其他Stakeholders做演示的环境,也是从develop分支出来的

release分支

当所有计划好的feature都完成之后,团队会基于develop分支创建release分支,此时:

  • 持续集成系统会基于release分支产生新的构建,构建结果称为Beta构建(Beta Builds)
  • 测试团队(QA)基于Beta构建进行回归测试(Regression Testing)
  • release分支不接受任何新的功能增加
  • 开发团队在release分支上进行Bug修复,同样,修复Bug时是否需要创建自己的代码分支,取决于团队自己的决定
  • 当质量达标,团队验收之后,进入release流程,此时,基于release分支创建release tag,同时将release分支合并回develop分支,以将release分支中的bug修复带入develop分支。在建完release tag并将代码合并回develop分支后,可将release分支删除。上图中没有体现这一步
  • 上图中展示的是将release分支合并到master分支,然后在master分支上建release tag,这样做是不妥的,因为合并到master分支的代码并没有经过测试,所以release tag不能建立在master分支上

hotfix分支

在某个版本发布之后,有可能会得到用户的反馈,有些是功能性的,有些则是影响用户使用的问题。对于功能性的反馈,可以与用户商量,或者团队自己决定,是准备在下一个版本中加入,还是基于用户现在的版本为用户专门定制。如果是后续版本再支持,则遵照上述feature分支的策略即可,但如果是基于用户现在使用的版本进行定制,则需要走Hotfix的流程

  • Hotfix分支从已经release的tag创建,找到已有的tag,然后基于tag新建Hotfix分支即可
  • Hotfix分支的工作流程可以参考develop分支
  • Hotfix开发完成并检验通过之后,基于Hotfix分支创建tag,标记为某一个Hotfix
  • 根据当前所修复的问题是针对该特定用户的(比如在界面上增加用户公司的名称与logo),还是针对所有用户的(比如某个bug的修复),以此决定是否需要将改动合并到develop分支
  • 删除Hotfix分支

从上面的流程可以看出,除了develop分支(或者master分支)为长期存在的分支之外,其它的分支都为辅助分支,在工作完成之后可以立即删除。为了满足代码评审(Code Review)而创建的开发人员自己的分支,一般都是即用即删。

以上就是Git Flow的整个流程,应该是已经介绍的比较细致了。在平时的工作和自学中,我都是以Github作为代码托管平台的,因此,本文的内容仍然是以Github为基础,包括接下来有关Azure DevOps Pipeline的介绍,也是与Github进行集成的。

Azure DevOps中Git Flow相关功能介绍

在上面的介绍中,不止一次提到持续集成系统,比如,当有代码签入feature分支或者develop分支时,持续集成(Continuous Integration,CI)系统会自动进行编译,然后触发持续发布(Continuous Delivery,CD)系统完成自动化部署。这些CI/CD系统所执行的自动化任务,需要人为地反复定义并触发吗?其实并不需要。现在流行的持续集成系统基本都已成熟,比如Jenkins,它的Pipeline功能直接支持Multi-Branch,每当有新的分支创建,或者代码签入,都会触发Jenkins创建新的Job,并触发相应的CI任务。Azure DevOps在这部分也做得非常好,而且它是云端服务,简单易用,对于开源项目是完全免费的。

首先,当你在Github中新建了一个repo,并且在Azure DevOps中配置了一个Project,使其从Github拉取代码时,你会发现,Github repo的Webhook里已经自动为你加上Azure DevOps所需的Webhooks:

不用管它,我们设想两个场景:

  1. 当开发人员准备向feature分支合并代码时
  2. 当feature分支出现代码签入时

下面看看,如何在Azure DevOps中进行配置,以实现上述两个场景。在这个实验中,我的Github Repo有三个分支:

  • master:暂时没用到
  • dev:开发主线,保持了最新代码
  • features/a1:功能代号为a1的开发分支

目前团队都在集中开发features/a1功能,由于团队选择较为严格的Code Review流程,因此,开发人员在进行自己工作之前,都是从features/a1创建自己的工作分支,比如就叫features/a1-daxnet吧,以便在代码签入features/a1分支的时候,能够产生Pull Request并申请代码审查。工作分支的名称可以自己决定,但团队需要达成共识,因为这个名称之后会被Azure DevOps用到。

现在,进入Github Repo的Settings页,在Branches设置页面中,在Branch protection rules设置下,新建一个规则(Rule),在Branch name pattern中,输入features/a1(也可以使用规则来定义一组分支),然后,勾选Require status check to pass before merging:

注:如需Code Review,则还需要勾选Require pull request reviews before merging,在这里就不演示了。然后,回到Azure DevOps,针对Github Repo创建CI,在CI的Trigger选项中,启用Continuous integration,以保证每当有代码签入指定的分支,就会触发持续集成。在Branch filters中,添加features/*分支,表示以features作为开头字符的所有分支,都需要进行持续集成,确保编译通过:

启用Pull request validation,在Branch filters中,添加features/a1,表示当有Pull Request需要合并到features/a1分支时,也需要进行持续集成,以确保编译通过。注意,目前我们不涉及Repo被Fork的情况,所以我们不勾选Forks选项:

OK,基本设置就是这样,非常简单。接下来,我们开始开发新的功能。首先,在Github页面基于features/a1,创建分支:features/a1-daxnet:

刚刚创建完新的分支,Azure DevOps就已经开始工作了,可以看到,Build Pipeline已经完成了新分支的编译:

下面,我要开始修改代码了,在代码修改完成本地编译通过之后,我将代码提交到features/a1-daxnet分支:

再次查看Azure DevOps的Build Pipeline,可以看到,CI已经开始帮我们编译新的代码提交了:

OK,再次不管它,现在,我希望将代码合并到features/a1分支,于是,我到Github上创建Pull Request,此时Github会提示,代码校验还在进行中,并等待Azure DevOps的编译结果:

回到Azure DevOps,可以看到,Build Pipeline正在进行Pull Request编译:

等待编译成功后,开发者就可以将代码合并到features/a1分支了。当然,这里我没有强制要求必须要等代码编译成功才能合并分支,因此,即使是编译没有完成,上图中的Merge pull request的按钮也是可用的。

总结

本文首先介绍了Git Flow分支策略,并结合了实际应用介绍了Git Flow的详细步骤,然后基于Azure DevOps介绍了在实际应用中,Azure DevOps Build Pipeline对Git Flow的支持。本文所介绍的内容并不能完全适用于所有的软件项目,尤其是SaaS项目,所以在开发过程中,团队还是应该根据自己的实际需求来定制自己的开发流程,在保证软件质量的前提下,提高开发体验和团队生产力,探索寻求适合自己的实践流程。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容

  • [转载]https://www.ibm.com/developerworks/cn/java/j-lo-git-m...
    张志_koen_zhang阅读 2,079评论 0 2
  • 原文推荐: A successful Git branching model 这个文章讲的是Git分支模型的原理及...
    SonyaBaby阅读 1,451评论 0 0
  • 什么是GitFlow? Git Flow定义了一个项目发布的分支模型,为管理具有预定发布周期的大型项目提供了一个健...
    一天大佬阅读 11,832评论 0 5
  • 简介 现代软件开发过程中要实现高效的团队协作,需要使用代码分支管理工具实现代码的共享、追溯、回滚及维护等功能。目前...
    Lucas66阅读 7,897评论 0 5
  • 上个月底31号来的,这个月觉得还早不着急,但是25号上午没有征兆就来了,又整整提早了6天。那天早上还在想会不会中,...
    萍水相逢0923阅读 93评论 0 0