代码开发模式最佳实践
1. 前言
本文针对 Git 版本控制系统的使用场景,描述了在一般情况下应当遵守的通用原则。接着,分别针对使用 “主干开发” 和 “分支开发” 这两种研发模式。最后,分析 gitflow 模式,给出阿里分支管理的最佳实践,详细说明了在应用开发平台上的整个研发流程中各个阶段的实际工作过程。
2. 最佳实践概述
Git Flow 定义了一个项目研发的分支模型,为管理具有预定发布周期的大型项目提供了一个健壮的框架,但对高并发敏捷型开发场景,过于复杂和低效。在(微)服务化框架下,高并发项目(需求)研发场景下的一种高效分支策略:高并发开发场景下,如何开始一个新功能(Feature)的开发,而不影响别的功能(Feature);创建了多分支,如何管理,每个分支是干什么的,哪些分支已经合会主干;发布或预发时怎么处理开发中的新功能(Feature);线上(生产)环境出现故障,如何快速修复, 修复代码如何分发到大量处于开发中的新功能上(Feature)。
【适用场景】
- 传统的瀑布研发模式
- 基于微服务的敏捷研发模式
- 远程多地协同的研发模式
【方案架构】
【方案优势】
- 支持传统大项目(周期长)研发场景
- 支持敏捷项目研发场景
- 支持高并发多分支研发场景
3. 前置条件
在执行本文操作前,请完成以下准备工作:
- 所在公司已购买并开通云效项目管理、需求管理产品模块。
- 已注册云效账号并完成认证,可以登录云效平台。
- 完成云效产品培训并通过相关考试。
- 加入云效的钉钉答疑群(联系本公司云效接口负责人入群)。
- 已完成应用管理,其中有应用是主干模式和分支模式。
4. 工具准备
- 本方案使用 Chrome 浏览器,需提前准备。
- 安装钉钉或企业微信。
5. 名词解释
名词 | 说明 |
---|---|
代码变更集 | commit,用于管理开发人员提交的一次代码变更,是 Git 版本控制系统中管理的变更单元。 |
主干 | 即 master 分支。是 Git 代码库中的默认分支,通常在研发流程中起着特殊的作用,在某些场合下不允许随意进行更改。 |
分支 | branch 分支。一般情况应通过应用平台创建,用于隔离同时进行的研发活动,如代码实现、集成、发布版本维护等。 |
远程代码仓库 | 托管在服务器上由项目团队管理的的 Git 代码仓库,为所有团队成员共享,作为持续集成系统的代码输入。 |
本地代码仓库 | 每个开发人员开发代码时,在本地通过 git clone 命令创建的代码仓库副本,需要定期与远程代码仓库通过拉取(pull)和推送(push)进行同步。 |
6. 主要代码模式
云效平台主要支持如下三种代码模式的开发场景:“主干开发-分支发布”、“分支开发-主干发布”和“分支开发-分支发布”,下面将分别对上述三种模式的最佳实践方式进行介绍。
6.1 主干开发-分支发布
我们使用默认分支 master 作为唯一的开发分支(即主干),所有开发人员同时在此主干上进行代码的开发与集成;在发布时,通过创建独立的集成发布分支来追踪发布的代码版本。
在此开发模式下,云效平台可帮助开发人员在代码变更提交后进行编译、单元测试以及代码质量扫描的单测集成,并在代码合并后进行代码集成的自动化验证。
6.1.1 优势
- 代码合并在提交至开发主干后即完成,无需进行额外步骤。
- 不存在长时间不合并主干的开发分支,降低代码集成风险。代码集成时间点的提前,有利于持续集成的实施,能够及早获得反馈并修复集成问题。
6.1.2 问题
- 开发主干上的集成问题会阻塞整个团队的开发活动,必须及时解决或进行代码回滚。因此,对开发人员合并代码、解决冲突以及排查问题的能力要求较高。
- 由于只有一个主干用于开发活动,因此,不适合并行开发场景和敏捷研发场景。
- 工作在同一主干的开发团队必须共同制定和遵循开发纪律,以维护主干代码的健康程度,要求团队成员之间有顺畅的沟通渠道和开放合作的团队文化。
6.1.3 研发模式流程
开发开始:开发开始时,开发人员首先在云效平台的对应项目中,针对需要开发的应用模块申请变更。然后,将远程仓库 master (主干)分支上的最新代码拉取至本地仓库后,即可开始在本地 master 分支上进行开发,无需建立任何额外分支。
【操作步骤】:
- 选择已创建的变更集进行申请变更(代码分支)。
- 选择后缀带 trunk 的应用(主干开发模式)。
- 值得注意的是:开发人员应当尽快完成本地代码变更,并将其合并到远程代码仓库中。在开发完成前,开发人员应适时拉取远程仓库 master (主干)分支上的最新代码至本地分支,完成与本地代码的合并,且通过本地验证。(若条件允许,此操作推荐使用
git pull –r
或git fetch
+git rebase
命令完成,以避免git pull
和git merge
命令产生额外的合并提交,使代码库变更历史记录更为简洁。)
- 选择已创建的变更集进行申请变更(代码分支)。
开发结束:
【操作步骤】:
- 将所有本地代码更改组织成为合适的变更集,提交至本地仓库。
- 拉取远程仓库 master 分支(主干)上的最新代码,完成与本地开发分支代码的合并。 (若条件允许,此操作推荐使用
git pull –r
或git fetch
+git rebase
命令完成,以避免git pull
和git merge
命令产生额外的合并提交,使代码库变更历史记录更为简洁。) - 将本地 master 分支推送(push)至远程仓库。
合并集成:在使用主干开发模式时,代码的合并与集成实际上开始于开发完成阶段。当开发人员将本地开发分支推送到项目开发分支上时,代码变更已经在开发人员的本地仓库完成了合并。因此,代码的集成能够在无需人工干预的条件下顺利完成。
然后,开发人员在应用平台上提交集成,创建出独立的集成发布分支。持续集成机制将被触发,打出集成包并开始执行自动化验证。自动化验证通过后,代码变更的集成结束。
云效平台支持多套集成环境,可按时按需进行集成。推荐使用一套集成环境为最佳,便于管理维护和节省成本。采用自动化回归验证,来提高集成环境使用效率和吞吐量。推荐的最佳方式是每个需求(开发任务)逐个进集成,逐个出集成。
之后,云效平台会自动启动集成流水线。从集成发布分支开始,自动进行冲突检查、编译打包、部署环境、自动化验证,甚至发布上线,最后将集成发布分支合回 master。
若验证过程中出现任何问题,开发人员应当回滚集成操作并优先排查问题。然后,根据情况选择优先修复或者回滚代码变更,从而保证主干代码的健康状态。
发布: 完成集成并确认发布范围(已完成的需求、任务和需要包含的代码变更)后,发布人员需要在开发平台上选择相应的集成分支进行发布。发布结束后,在应用平台上选择合并到主干结束发布流程。集成或发布后,验证发现有缺陷或故障,可选择回滚。
紧急故障修复:使用主干开发模式时,只有一个主干开发分支,紧急修复与正常开发的流程无任何区别。开发人员直接在主干(master 分支)上进行开发并遵循同样的流程。
6.2 分支开发-主干发布
在此开发模式下,代码库中的默认分支 master(主干)用来存放已经完成集成和发布的最新代码。我们使用从主干创建的独立开发分支来支持并行的、且针对不同需求和任务的开发活动。在不同的开发分支上,各自独立,彼此隔离;开发分支的代码在合并回主干后进行集成、验证和发布。
此模式下,开发平台可帮助开发人员自动创建开发分支,在代码变更提交后进行编译、单元测试以及代码质量扫描的单测集成,提交集成时自动合并开发分支并进行代码集成的自动化验证。
6.2.1 优势
- 彼此隔离的开发分支可以提供可靠的代码隔离,能够保护并行的开发活动之间不会互相干扰和影响。
- 独立的开发分支隔离了不相关和未完成的代码变更,发布过程中无需冻结代码。
6.2.2 问题
- 开发主干上的集成问题会阻塞整个团队的开发活动,必须及时解决或进行代码回滚。因此,对开发人员合并代码、解决冲突以及排查问题的能力要求较高。
- 开发团队必须共同制定和遵循开发纪律,以维护主干代码的健康程度,要求团队成员之间有顺畅的沟通渠道和开放合作的团队文化。
- 对分支的创建和合并操作较多,会产生额外的分支维护成本。
- 开发分支会导致集成时间点延后,研发团队应当尽最大努力快速合并开发分支,降低集成风险。
6.2.3 研发模式流程
开发开始:开发开始时,开发人员在开发平台的对应项目中,针对需要开发的应用模块申请变更,并根据需要对开发平台创建的开发分支进行命名,开发平台会自动创建开发分支。随后,开发人员仅需将远程仓库的最新代码拉取(pull)至本地仓库,即可进行开发活动。
【操作步骤】:
- 选择已创建的变更集进行申请变更(代码分支)。
- 选择后缀带 branch 的应用(分支开发模式)。
- 设定分支名称,推荐云效平台自动生成,简单方便。
- 值得注意的是:每天工作结束前,开发人员都应保持本地代码变更同步到远程代码仓库的开发分支上(在本地分支上,
git status
命令结果不显示任何代码变更,且本地分支与远程开发分支完全同步)。另外,为了降低开发分支的集成风险,推荐开发人员在开发完成前,也应当适时拉取远程仓库 master 分支(主干)上的最新代码至本地仓库,然后在本地开发分支上使用git merge master
命令完成与主干代码的合并。
- 选择已创建的变更集进行申请变更(代码分支)。
开发结束:开发人员将所有的代码变更提交到本地代码仓库后,再推送至远程仓库的开发分支上。由于在独立的开发分支上进行开发,开发人员应当不需要对远程代码仓库的开发分支进行拉取(pull),可直接以快进(fast forward)的方式推送(push)本地的代码变更集。在开发过程中,开发人员需根据云效平台单测集成模块的反馈,随时修复代码问题,持续保持代码质量。
合并集成:测试通过后,开发人员在开发平台上选择需要进行合并集成的开发分支,进行提交集成操作。此时,云效平台创建出独立的集成发布分支,持续集成机制将被触发,打出集成包并开始执行自动化验证。自动化验证通过后,代码变更的集成结束。
云效平台支持多套集成环境,可按时按需进行集成。推荐使用一套集成环境为最佳,便于管理维护和节省成本。采用自动化回归验证,来提高集成环境使用效率和吞吐量。推荐的最佳方式是每个需求(开发任务)逐个进集成,逐个出集成。
之后,云效平台会自动启动集成流水线,从集成发布分支开始,自动进行冲突检查、编译打包、部署环境、自动化验证,甚至发布上线,最后将集成发布分支合回 master。
若验证过程中出现任何问题,开发人员应当回滚集成操作并优先排查问题。然后,根据情况选择优先修复或者回滚代码变更,从而保证主干代码的健康状态。所有合并集成操作由开发平台自动完成,在不发生合并冲突时,无需开发人员手工介入。
发布:通过集成验证的发布候选包应当立即进行部署和发布。发布之后,研发流程结束。
紧急修复:紧急修复与正常开发的流程相同。在应用平台上申请变更时,可根据需要选择在之前版本的合并发布分支上开始,或基于主干新创建开发分支开始进行开发,推荐基于主干新创建分支。之后的合并、集成和发布过程,遵循正常的开发流程即可。
6.3 分支开发-分支发布
在此模式下,代码库中的默认分支 master(主干)用来存放已经完成集成和发布的最新代码。我们使用从主干创建出的独立开发分支来支持并行的,且针对不同需求和任务的开发活动。不同的开发人员工作在不同的开发分支上,各自独立,彼此隔离;开发分支上的代码变更在与主干集成并锁定主干后,形成发布分支,用来支持集成验证和验证失败后的集成回滚。发布成功后,发布分支的代码变更则被合并至主干,更新主干上的最新代码状态。
此模式下,开发平台可帮助开发人员自动创建开发分支,在代码变更提交后进行编译、单元测试以及代码质量扫描的单测集成。提交集成后,自动创建合并集成分支,在代码合并后进行代码集成的自动化验证并最终将分支上的代码变更合并回主干。
6.3.1 优势
- 彼此隔离的开发分支可以提供可靠的代码隔离,能够保护并发进行的开发活动之间不会互相干扰和影响。
- 独立的发布分支与开发分支隔离了不相关和未完成的代码变更,发布过程中无需冻结代码。
- 经开发分支与主干合并而形成的集成分支有效地隔离了潜在的集成问题,保证主干上的代码已经通过了集成、验证、发布并维持着非常健康的状态,也进一步支持了其它开发活动的稳定和可靠。
6.3.2 问题
开发分支会导致集成时间点延后,研发团队应当尽最大努力快速合并开发分支,降低集成风险。
6.3.3 研发模式流程
开发开始:开发开始时,开发人员在开发平台的对应项目中,针对需要开发的应用模块申请变更,并根据需要对开发平台创建的开发分支进行命名,开发平台会自动创建开发分支。随后,开发人员只需将远程仓库的最新代码拉取(pull)至本地仓库,即可进行开发活动。
【操作步骤】:
- 选择已创建的变更集进行申请变更(代码分支)。
- 选择后缀带 branch 的应用(分支开发模式)。
- 设定分支名称,推荐云效平台自动生成,简单方便。
- 值得注意的是:每天工作结束前,开发人员都应保持本地代码变更同步到远程代码仓库的开发分支上(在本地分支上,
git status
命令结果不显示任何代码变更,且本地分支与远程开发分支完全同步)。另外,为了降低开发分支的集成风险,推荐开发人员在开发完成前,也应当适时拉取远程仓库 master 分支(主干)上的最新代码至本地仓库,然后在本地开发分支上使用git merge master
命令完成与主干代码的合并。
- 选择已创建的变更集进行申请变更(代码分支)。
开发结束:开发人员将所有的代码变更提交到本地代码仓库后,再推送至远程仓库的开发分支上。由于是在独立的开发分支上进行开发,开发人员应当不需要对远程代码仓库的开发分支进行拉取(pull),可直接以快进(fast forward)的方式推送(push)本地的代码变更集。在开发过程中,开发人员需根据云效平台单测集成模块的反馈,随时修复代码问题,持续保持代码质量。
合并集成:测试通过后,开发人员在开发平台上选择需要进行合并集成的开发分支,进行提交集成操作。此时,开发平台会自动进行以下操作:
- 锁定主干。禁止其它开发分支进入合并集成流程。
- 基于开发分支的最新代码创建集成分支,并将主干(master 分支)上的最新代码合并到集成分支。若出现合并冲突,合并集成将会失败,开发人员应回滚集成操作,在本地解决冲突后冲突新提交集成。
- 触发持续集成机制,进行集成验证。若集成验证通过,则集成包可作为发布候选使用;若集成验证失败,开发人员应回滚此次合并集成操作,解除对主干的锁定,再次进入开发环节修复集成问题。然后,重新进行合并集成。
- 云效平台支持多套集成环境,可按时按需要进行集成。推荐使用一套集成环境为最佳,便于管理维护和节省成本。采用自动化回归验证,来提高集成环境使用效率和吞吐量。推荐的最佳方式是每个需求(开发任务)逐个进集成,逐个出集成。
- 之后,云效平台会自动启动集成流水线,从集成发布分支开始,自动进行冲突检查、编译打包、部署环境、自动化验证,甚至发布上线,最后将集成发布分支合回 master。
- 若验证过程中出现任何问题,开发人员应当回滚集成操作并优先排查问题。然后,根据情况选择优先修复或者回滚代码变更,从而保证主干代码的健康状态。所有合并集成操作由开发平台自动完成,在不发生合并冲突时,无需开发人员手工介入。
发布:通过集成验证的发布候选包应当立即进行部署和发布。发布之后,配管人员在应用平台上进行合并主干操作,将合并分支上的代码变更集合并到主干,同时解除对主干的锁定,允许其它开发分支进行合并集成。集成或者发布后,验证发现有缺陷或故障,可以选择回滚。
紧急修复:紧急修复与正常开发的流程相同。在应用平台上申请变更时,可根据需要选择在之前版本的合并发布分支上开始,或基于主干新创建开发分支开始进行开发,推荐基于主干新创建分支。之后的合并、集成和发布过程,遵循正常的开发流程即可。
7. Git Flow 分析
Git Flow 定义了项目研发的分支模型,为管理具有预定发布周期的大型项目提供了健壮的框架,如它起源用于 Linux 内核开发的版本控制工具。对敏捷模式下的高并发需求交付,此流程比较复杂低效。
7.1 正常单开发分支流程
- 从 develop 分支切换出一个新分支,依据分支特点进行命名。功能即 “feature-*”,bug 即 “fixbug-*”。
- 开发者完成开发,提交分支到远程仓库。
- 开发者发起 merge 请求(可在 gitlab 页面 “New merge request”),将新分支请求 merge 到 develop 分支,并提醒 code reviewer 进行 review。
- code reviewer 对代码 review 后,若无问题,则接受 merge 请求,新分支 merge 到 develop 分支,同时可删除新建分支;若有问题,则不能进行 merge,可 close 该请求,同时通知开发者在新分支上进行相应调整。调整后,提交代码重复 review 流程。
- 转测时,直接从当前 develop 分支 merge 到 pre-release 分支,重新构建测试环境完成转测。
- 测试完成后,从 pre-release 分支 merge 到 master 分支,基于 master 分支构建生产环境完成上线。并对 master 分支打 tag,tag 依照 “版本号_上线时间” 方式命名,如 v1.0.0_2019032115。
7.2 测试环境 Bug 修复流程
- (上一版本已转测但未上线,下一版本又已在开发中且部分已合并到了 develop 分支)过程中,转测后测试环境发现的 bug 需要修复。
- 但是,develop 分支此时又有新内容且该部分内容目前不计划转测,需要从 pre-release 切换出一个 bug 修复分支。
- 完成后,需同时 merge 到 pre-release 分支与 develop 分支,merge 时遵照 “正常开发流程”。
7.3 生成环境 Bug 修复流程
- 紧急 Bug 修复,需要从 master 分支切出一个 bug 修复分支。
- 完成后,需同时 merge 到 master 分支与 develop 分支(若需测试介入验证,则可先 merge 到 pre-release 分支,验证通过后再 merge 到 master 分支上线)。
- merge 时遵照 “正常开发流程”。
8. 云效的分支流程
master 绝对稳定,bugfix、hotfix 和 feature 均从 master 拉分支开发,发布分支(集成分支)都是实时生成。统一流程:拉分支 > 提交集成 > 发布(合并主干),所有操作云效平台一键操作。
9. 代码库推荐原则
9.1 目录结构
使用 Git 版本控制系统时,对代码的目录结构没有特殊要求。应以项目的实际需要(技术栈、构建工具等),以及能够清晰展示代码文件之间逻辑关系的组织方式为准。例如,在选择使用 Maven 构建项目时,可遵循 Maven 推荐的标准目录结构。
9.2 命名规则
在对 Git 版本控制系统管理的对象进行命名时,应该使用清晰表意、简洁明了的名称,能够回答 “它是什么” 的问题。同时,也可通过注释、备注等辅助方式来解释 “为什么有它” 的问题。
9.2.1 代码库命名
原则上,代码库的命名应该与代码库中管理的代码模块、服务、应用或系统的名称保持一致。通常使用简洁清晰的名词或者组织内定义的代号,具体名称应遵循组织架构中关于项目管理和代码管理的相关内容。
9.2.2 分支命名
在 Git 版本控制系统中创建代码库时,其中的默认分支 master 即为主干,一般在项目研发流程中承担着特殊意义,其使用方式取决于项目中采用的研发模式。
其它分支的命名应该使用前缀,清晰地描述其用途。如开发分支(feature, task)、合并集成分支(merge)、发布分支(release)等,并结合使用短语或可追溯的编号来描述分支内包含的代码变更内容,例如:
9.2.3 代码变更命名
每次代码变更或 “提交” 都必须使用合适的注释信息来描述本次代码变更的主要内容、目的、关联的工作项以及任何需要额外提及的细节信息,以帮助其他项目成员更容易地识别变更内容、获取关联的背景和上下文。
通常,Git 的代码变更注释信息可包含多行,例如:
- 首行为摘要,简短描述关联工作项,并尽量使用业务领域语言描述主要工作内容。如果项目中使用了任何需求管理或缺陷管理系统,应该首先包含可以在系统中追溯的工作项编号。
- 空行分隔符,用于分割摘要与细节信息。
- 行或多行文字,通常用技术语言来描述代码变更实现的方案细节和需要提及的上下文知识。
9.3 文件类型和内容
“版本化控制一切” 是敏捷软件开发方法的重要原则之一。但这并不意味着,一切与项目研发过程相关的文件都适合提交到版本控制系统之中。纳入到版本控制系统的文件应当以纯文本类型的文件为主,包括但不限于:
- 代码文件:代码实现、接口定义、头文件、测试代码、项目构建定义等文件。
- 资源文件:从源代码中分离出的文字内容和需要在项目团队中共享的其它文档。
对于二级制文件、能够通过项目构建过程产生的文件以及其它不需要在开发过程中共享的文件,不建议纳入到版本控制系统中,比如:
构建输出文件:此类文件通常产生于构建过程中,在项目研发过程中不会直接对它们进行修改。因此,项目构建输出结果文件应当纳入到软件包仓库进行管理,而项目构建的过程文件应该只临时存放在本地。总之,该类文件均不应被提交到版本控制系统中。
第三方软件包:是代码运行时的必要依赖,这些外部依赖应当以配置信息的方式(名称、版本、来源等)放入项目配置文件,软件包本身应当在构建过程中通过这些信息向软件包仓库请求获取。版本控制系统既无能力妥善管理这些文件,也不必对其进行管理。
- 本地开发环境特有的配置信息:应尽可能地存放在项目目录之外(如开发用户的主目录下),而 IDE 生成的配置文件则包含了本地环境特有的配置信息。这些信息不是项目开发过程中需要共享的公共数据,因而不需要提交到代码库中进行版本化管理。
这些不应纳入版本管理的文件应当清晰地定义在 Git 代码库根目录的 .gitignore 文件中,以防新文件创建时被加入到代码更改的提交列表中。
10. 提交代码变更
项目研发过程中,每个开发人员都应保证每日至少提交一次代码变更到 Git 版本控制系统中。及时提交代码变更将大大降低代码资产遗失的风险,也是实施持续集成的前提条件。因此,当项目实际情况允许时,开发人员更应当提高代码变更的提交频率。由于 Git 的分布式特性,开发人员在提交代码变更到本地仓库后,还应及时与远程代码仓库进行同步。
在提交代码变更时,开发人员应当尽最大努力将代码变更集的粒度保持在合适的大小:
- 每个提交的代码变更集,应当只与一项需求或任务有关。过大的变更集会增加命名和注释的难度,影响代码评审效率,也不利于代码维护时对变更集的定位。
- 另一方面,相关的代码变更应当包含到同一个变更集中。代码变更集过小会导致代码库中存在互相关联的多个变更集,这会对分支合并、变更回滚等操作产生不利影响。
因此,开发人员在使用 Git 版本控制系统时,可以在提交变更到本地仓库之前,通过调整索引区的文件列表来控制每次变更集的范围;而在本地仓库的变更集被推送到远程仓库之前,开发人员仍然也可以使用 Git 命令重新更改、拆分、合并甚至取消这些已经提交的变更集。
在完成所有代码变更的提交之后,开发人员本地的工作空间内不应再保留任何未经提交的代码变更(git status
命令结果不会显示任何代码更改信息)。
提交代码变更时,开发人员应当保证提交的代码能够完全通过编译、单元测试并通过高危漏洞代码扫描。开发平台中的单测集成模块会持续对提交的代码变更集进行编译、单元测试以及代码质量扫描。开发人员应当根据结果,对编译错误、单元测试错误、高危漏洞以及根据团队自定义的配置规则发现的其它代码质量问题,进行优先修复。
11. 使用 GitLab API 时 Token 的生成方法
登录 GitLab,点击右上角的用户头像,在下拉菜单中选择 Settings。
点击左侧菜单中的 Access Tokens,在右侧页面中设置新建 Tokens 的名称、到期时间以及此 token 的权限范围。完成后,点击 Create personal access token 按钮。
操作无误后,会显示 token 值、token 名称、创建时间、到期时间、权限范围等信息。token 创建完成后,可以在 api 中使用。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论