一种适用于大规模应用系统双模研发的GIT分支模型(上篇)

889 阅读16分钟
原文链接: mp.weixin.qq.com

背景

近年来,传统企业IT研发面临的“双模研发”场景越来越多,在完成瀑布式研发任务的基础上还要承载新市场形势下的快速迭代的研发需求,由于传统企业 IT研发的历史原因与系统应用场景的特殊性,无法直接采用现有成熟的Git代码分支模型进行代码管理,如何在这种复杂协作型项目中进行代码分支管理是项目管理和开发人员亟待解决的问题。本文分析了传统企业软件研发的特点,提出了一种适用于复杂协作型项目、兼容“瀑布 +敏捷”双模研发的Git代码分支管理模型,并根据传统企业 IT研发特点制定了相应的分支管理与操作规范,解决了大团队协作研发中的诸多代码管理难题,并在农业银行信贷管理系统群(C3 )中进行了应用实践。

作者:宋绍磊、葛江浩、王丽敏

供职于中国农业银行研发中心,从事信贷管理领域系统研发工作,致力于银行大型IT系统端到端全流程敏捷转型的研究与实践。

常见的Git分支模型介绍

Git是目前世界上最先进的分布式版本控制系统,可以有效、高速的处理从小到非常大的项目版本管理。Git基于分支进行代码开发,分支模型是开发团队为了更有效的对代码进行管理而提出的分支管理方式。为了使 Git能够适合企业复杂的开发场景、更好的与持续集成、持续交付流水线进行集成,不同的研发团队根据自己的系统架构、项目特点与产品的交付方式设计了不同的分支模型。随着敏捷研发等新的研发模式逐渐被软件研发行业认可,分支管理模型作为代码管理中的重要组成部分成为大家越来越关注的话题。由于历史原因和系统应用场景的特殊性,很多项目在开发过程中经常存在瀑布与敏捷两种模式并存的情形,如何在这种复杂协作型项目中进行代码分支管理是项目管理和开发人员亟待解决的问题。

业内都在探索适合自己系统与团队特色的分支模型,流行的分支模型有Git flow模型、 Github flow模型、主线开发模型等。

(1) Git flow:如图1所示, Git flow是基于Git的强大分支能力所构建的一套软件开发工作流,将软件生命周期中的各类活动归并到不同的分支上,实现了软件开发过程不同操作的相互隔离。 Git flow 包含 Master、 Develop 两个永久存在的长期分支和 Feature、 Release、Hotfix 等短期辅助性分支, Develop 分支用于代码开发,Master 分支用于版本发布,完成代码开发并准备发布时所有的代码变更都合并到  Master 分支;辅助性分支为短期分支,用于完成功能开发与特性跟踪、产品的发布准备以及快速修复线上问题。Git flow  的优点是分支清晰可控,缺点是相对复杂,需要同时维护两个长期分支,同时 Feature 分支长期存在时容易产生代码不一致问题。

图1 Git flow

(2)Github flow :Github flow 是 Git flow 的简化版,它是  Github.com 使用的工作流程。它只有一个长期分支 Master,从 Master  拉出新分支进行代码开发,新分支开发完成后向 Master 发起一个 pull request(简称 PR),请求进行代码评审与分支合并。Github flow 的最大优点就是简单,适于“持续发布”的产品,缺点是不适用于产品上线时间不确定等复杂的开发场景。

(3)主线开发模型: 如图2所示,主线开发模型是同一个产品的所有的开发人员共享一个 trunk,开发人员可以有自己的私有分支,但所有修改最后都会回到主干,只有在  Release 时才会创建 Release Branch,由 Release Engineer  进行维护,发布分支是主干某个时点的快照,必要时通过 cherry-pick 从主干挑拣代码到发布分支。基于主干的开发的优点是保证了所有用户看到的都是同一份代码的最新版本,避免了合并分支时的麻烦,缺点是不适于瀑布开发模型,同时对开发人员和发布分支的维护人员的技术要求比较高。

图2 主线开发模型

 纵观大型企业面临的市场环境,产品快速迭代的压力扑面而来,谁先推出符合市场需求的产品谁就占领了先机,对企业IT 研发的快速交付能力提出了新的要求和挑战,各大型企业IT研发领域都提出了敏捷研发的要求,同时对研发中的代码管理方式提出了新的要求。

但由于传统企业本身业务的特殊性,软件研发存在很多特殊研发场景:

  • 产品线庞杂,开发架构、运行架构各异,且存在大量遗留系统;

  • 很多IT产品研发往往有着明确的需求和明确的研发时间期望,并不完全符合经典的敏捷场景;

  • 研发团队规模较大,IT管理文化有别于互联网企业等;

  • 传统IT研发交付测试的产品不一定能够及时投产,存在长期处于测试并迭代优化的状态,同时由于业务的复杂性、多变性及涉及部门的多样性,需求变更、延期多,导致产品交付日期不可控,存在长期未上线的功能,并且功能之间存在较强的代码依赖性等问题。

现有的分支模型各有千秋,都有最佳的应用场景,但由于传统企业IT研发团队与系统的特殊性,不能直接照搬某一种分支模型。为了兼容“瀑布 +敏捷”的双模研发,对代码分支管理提出了更高的要求,如何探索与实践高效、易用的分支模型越来越受到传统企业研发领域的关注。

基于传统企业IT双模研发场景的特点,我们在充分研究业内典型分支模型的基础上提出了一种适用于复杂协作型项目、兼容“瀑布 +敏捷”双模研发的全场景代码分支管理模型。

3.1 全场景分支模型的组成

如图3所示,我们提出的全场景分支模型包含 Master分支、Dev分支、 Test分支3个长期分支和功能分支、投产分支、其他测试分支 3类短期分支。

图3 全场景分支模型

  • Master 分支是主分支,始终保持最新的投产在运行代码,通过标记区分不同的投产窗口(投产窗口是系统的上线时点, 对应一个唯一的正式代码版本,如图中“窗口1”、“窗口2”、“窗口 3”所示),所有其他分支都从 Master 分支创建,普通开发人员不能直接在  Master 分支进行代码推送,必须通过拉取请求的方式进行代码更新;

  • Dev 分支用于代码的存储、共享及协作开发,不合并回 Master  分支,根据具体研发情况对 Dev 分支进行定期清理;

  • Test 分支用于发布功能测试,保持功能测试的最新代码,根据运行情况从 Master  分支进行阶段性更新,普通开发人员不能直接在Test分支进行代码推送,只能通过拉取请求的方式进行代码合并,根据具体研发情况对Test 分支进行定期清理;

  • 功能分支(即特性分支)从 Master 分支创建,用于管理某个功能的代码,用于发布功能测试与投产,开发人员一般不直接在功能分支进行代码提交,而是通过将 Dev 分支已经开发完成的代码通过工具整理到功能分支;

  • 投产分支包含 Rel 分支和  Hotfix 分支,用于投产准备及投产发布,从 Master 分支创建,投产完成后将其合并到主分支并删除,其中  Hotfix 分支用于紧急缺陷修复;

  • 其他测试分支是临时测试分支,如正式上线前的区域性测试等,可以直接从Test分支新建分支,也可以从  Master 分支拉取分支后再合并待测试内容。

在开发任务分解完成后,开发人员基于Dev分支进行协作开发,开发完成后需要进行功能测试时,基于最新的 Master分支新建功能分支,开发人员将待测试内容通过cherry-pick的方式从Dev 分支整理到功能分支,并通过在线pull request的方式发布到Test分支进行测试,测试完成后同样通过 pull request的方式发布到投产分支进行投产,投产完成后对所有的短期过时分支进行清理。

3.2 通过共享开发分支实现瀑布型场景的即时研发

在双模研发项目中的瀑布型开发场景是需要进行长期开发的项目,瀑布型开发中往往涉及到跨职能组或部门的大团队协作,经常存在一个或多个大型系统的协同研发,由于项目的特殊性经常面临项目周期不可控、开发阶段需求尚未完全明确、在项目最终投产前存在大量需求变更、延期等常见问题。

在此开发场景中,开发人员可以在需求粒度、投产日期不完全明确的情况下直接基于 Dev 分支进行代码修改提交,待到开发功能基本确定、测试点基本明确的情况下,申请功能分支,将  Dev 分支已经完成开发的功能代码挑拣 (通过 Git 的 cherry pick 命令实现)到功能分支,将功能分支合并到 Test  分支进行功能测试,在投产时将功能分支合并到 Rel 分支进行投产验证及投产包构建,此流程能够很好兼顾瀑布型研发开发周期长的特点,方便了研发功能的整体规划与投产。

3.3 通过短平快的分支实现迭代型场景的研发

在双模研发项目中的迭代开发场景包括临时项目、紧急变更或缺陷修复等,在此类开发场景中,开发人员直接申请新的功能分支,基于最新的投产代码进行开发,开发完成后将功能分支合并到 Test  分支进行功能测试,完成功能测试后合并到 Rel 分支进行投产验证与投产打包,此流程简单清晰,便于功能的快速测试与投产。

3.4 通过分支对齐避免未测试代码带入生产环境

分支对齐指的是多个分支之间的前后顺序,即若源分支有新增的 commit id,在该分支合并到目标分支之前,源分支是先于目标分支的,分支完成合并后则源分支与目标分支是对齐的。如下图所示,基于分支对齐,可以确定要发布投产的功能分支是否已经发布功能测试以及在功能测试发布后是否有新的代码修改,并通过分支评审的方式拒绝未完成测试的分支合并到投产分支,避免了传统配置管理中的人工代码整理导致的未测试的代码误发布到投产的问题。

图4 TFS中的分支对齐

3.5 通过分支的权限控制与多级评审机制确保版本安全

在全场景分支模型中,对分支添加了强制权限控制,开发人员拥有 Dev 分支与功能分支的代码提交、推送权限,但对于  Test 分支、Rel 分支、 Master 分支只能通过拉取请求进行合并,避免了代码的误修改。同时对于所有分支,开发人员只能增量修改、不能存量删除,保证了整个代码库的安全性与可追溯性。

在基于 Git 进行代码开发时,由于分支包含的是全量的系统代码,为了保证分支中修改代码的安全性,我们引入了可视化的多级分支评审机制,功能分支到  Test 分支,功能分支到 Rel 分支, Rel 分支到 Master 分支的拉取请求都设置了代码评审机制,针对研发模块进行了分支策略设置(如图 5所示),保证关键核心文件要经过系统控制人员审核、跨模块文件修改要经过对方的负责人审批,确保代码不会被误修改、误合并,并通过可视化的方法提高了协同研发与问题解决的效率。

图5 TFS中的Git 分支策略设置

3.6 通过代码分库实现关键配置文件的扎口式管理

在双模研发项目中,尤其是跨团队协同的大项目,部署环境依赖性文件、生产环境安全配置文件等核心文件需要进行特殊的处理,为此我们在分支拥有全量代码的基础上设计了关键代码分库存储的方式,即将特殊文件从主流分支中剥离,在另一个库中由专人负责配置管理,开发人员所见的分支拥有全量的开发环境的代码,在持续集成与版本发布的过程中,我们设计了文件自动替换的方式(如图 6所示),使整个过程对于开发人员来说是透明的,在保证了特殊文件便于开发人员操作的基础上保证了文件的安全性,确保测试文件不会误带入生成环境,同时通过自动替换的方式实现了代码的一次编译多环境发布。

图6 在TFS 的生成定义中配置自动化脚本

3.7 全场景分支模型在双模研发中的应用优势

与常见分支模型相比,全场景分支模型下具有以下优点:

(1)支持双模研发模式:支持瀑布、敏捷两种研发模式,有效应对复杂多变需求的并行开发、多时点上线;

(2)支持大团队协同开发:团队开发分支与功能特性分支相结合,适合跨职能组的大团队并行协同开发,在开发阶段所有开发人员的代码修改都会及时推送到 Dev分支,团队人员可以及时看到其他成员的代码更新,方便代码的实时共享和复用。

(3)有效避免了功能分支的长期存在引发的文件冲突问题:在全场景分支模型中,功能分支是“事后整理”,即功能开发完成并明确了测试与投产时间后再进行功能分支的申请与代码整理,避免了  Git flow 模型中先新建分支再开发导致的分支长期存在引发的大量文件冲突问题。

(4)简化代码依赖管理:由于最新的开发代码都可以在 Dev  分支获取,保证了所有代码依赖的都是最新版本,各开发模块和开发人员可以很好的解决代码依赖问题。每当代码变动,会及时反馈到代码依赖方,能够提前发现协作开发中出现的问题。

(5)有效应对复杂多变的需求和开发场景:在该分支模型中,开发人员先基于Dev 分支进行开发基于功能分支进行代码整理,能够有效应对需求边界不清晰、需求细节不明确、需求上线时间待确定等不确定的需求和代码拆分、合并、延期等特殊开发场景。

(6)分支代码的自主与持续发布:在该分支模型中,开发人员在完成功能开发后可以及时的进行版本的的自主发布,减少了人工操作,实现了版本的快速交付。

(7)代码强制评审:在该分支模型中,我们基于 pull request  实现了可视化的分支代码的多级强制评审,功能分支必须按序合并到测试分支、窗口分支和主分支,有效应对了代码合并过程中的误修改问题,提升了代码开发的质量。

(8)便捷的代码对比与分析:基于 Dev  分支的线性代码开发与 Master 分支的投产节点标记方便了开发人员进行代码的查找、历史代码的版本对比与分析。

同时,在实践中我们基于 Git 的开源特性定制了便于分支管理、持续集成、自动化测试的工具,将分支与功能工作项及投产窗口进行关联,实现了基于需求与功能的分支代码管理,并基于 TFS的可视化、流程化的方式(如下图所示)实现投产任务的统一管理与集中发布,完成了代码分支与研发工作的一体化管理。

图7 分支发布与产品部署

敬请期待下篇!