最近参与了一个多人协作开发的项目,在开发过程中遇到不少问题。例如,前端提交冲掉后端代码、代码冲突无法解决直接返工、A 提交 B 分支、直接提交 Master 分支等。本文是记录,也是思考如何更高质量地管理项目、进行多人合作项目的开发。
1. 版本管理的需求
1.1 版本标记
在正式环境,每一次发布之前都需要对版本进行标记。一方面是为了记录发布历史,另一方面是为了在必要时,能够迅速地回滚版本。比如,在 3 月 21 日 进行了一次正式环境的发布,Tag: V20180321,Message:新增 XXXX。在 3 月 29 日,运营人员要求立即下线一个跳转的链接。但是在距离上一次正式发布的时间段内,开发人员已经提交了新的功能代码,甚至可能已经合并到主仓库。这时,开发人员可以拉取 Tag: V20180321 版本的代码,修改之后再打上 Tag: V20180321-remove-xxx,即可进行测试、发布。
1.2 分支管理
在多人开发时,为了减少开发人员之间的相互干扰,强烈建议每个人都以功能的维度创建分支更新代码,一个功能一个分支。在项目排期分配的过程中,通常会将不同的功能、模块,划分给不同的人。在这种情况下,只需要提前约定模块之前耦合的部分,比如,接口、全局变量等,就能够满足协作开发的初衷:多人并行、缩短开发周期。
1.3 变更记录
对文件变更的记录是版本管理最基本的需求。变更记录是最原始的迭代数据,通过查阅变更记录,可以将功能和具体的代码行结合起来,既方便审计代码,也是给其他开发者的注释。
2. 为什么是 Git, 而不是 SVN
分支管理上的优势,让我们选择了 Git,放弃 SVN。
Git 上可以轻松地使用多个独立分支。同时很容易对这些分支进行创建、更新、删除、合并等操作。
另外一点是,Git 速度快,从各种压力测试数据来看,相较于 SVN,Git 在文件压缩、文件存储方面有着极高的效率。
3. Git 开发工作流
简单介绍一下项目开发团队背景:开发人员包括,三个前端、两个后端;项目 S 是一个 SaaS 项目,基于 PaaS 平台开发,平台提供 SVN 仓库进行代码管理。前端使用 Webpack + Vue.js,后端使用 Django,采用前后端分离的模式进行开发。
S 项目是一个在频繁迭代的项目,这一次是第五期。前面几期,主要有一个前端、一个后端配合开发。第五期,由于前端离职,两个前端新人+前端导师加入项目组。两个后端也有其他项目,并非 100 % 投入。
这种情况下,前端不熟悉项目、后端不能全身心投入。如果不采取一定的措施,势必导致项目延期,甚至污染早期的代码。
于是在新迭代伊始,我就将仓库迁移到 Git。同时,使用GitLab CI 将代码推送到 SVN 发布仓库,以更好地支持多人协作开发。
考虑到项目迭代周期短,我选择的是 Github Flow 的工作模式。下面是开发工作流:
以功能划分单元,每个功能新建一个分支,最终合并到 Master 分支。由于小的功能点特别多,频繁的创建分支,会导致分支太多;如果删除分支,又无法追溯版本。于是,约定在这一期迭代中,每个人持续跟踪一个自己的分支。在每次开发新功能之前,需要将 Master 合并到自己的分支,以保持本地版本最新。
4. MR/PR 流程
多人合作开发主要是通过多分支来实施。多分支管理的难点在分支的合并上。听过公司内部一个敏捷开发方向的专家分享,在他带领的团队出现过,合并代码比开发代码时间还长的情况。然后,通过解耦、优化流程,结合 CI 工具,最终每两个星期就能发一个版本,再结合 A/B 发布,能达到每周一个版本,快速迭代的奇效。
简单点讲,Github Flow 就是将每次新功能、BUG 修改等都新建一个分支。提交代码之后,发起一个 Merge Request(简称,MR)、或者 Pull Request (简称,PR)。再由项目其他成员讨论之后,反复修改、提交代码。最终达成一致之后,由具有 Merge 权限的成员合并到 Master 分支。
其中的 MR/PR 流程是保证模块正确耦合、高质量代码的关键。出现前端代码冲掉后端代码、冲突无法解决直接返工等问题的原因,正是因为 MR/PR 流程的缺失。
于是,前后端都指定了一位负责人,具有 Master 权限,负责 Review 其他成员的代码,处理其他成员发起的 MR/PR。其他成员作为 Developer 的角色存在于项目。Review 代码是一种能快速学习、提高代码质量的方式,如果项目内部能形成相互 Review 的习惯,对项目和自己都会有很大收益。