1. 版本控制器
早些年,主流的版本控制器主要是 svn、cvs 等,这些版本控制器有对应的操作页面,使用方便快捷,但是有一个通病,就是在进行多人协同工作时,团队成员之间的影响很大,比如说在团队协同工作过程中,如果有一个人忘记更新代码后直接提交代码,就会造成其他人的代码丢失的问题。这个问题的出现主要是因为 svn、cvs 等版本控制器主要是对整个仓库做一个镜像备份的原因,而近些年,git 越来越火,一方面因为它与其他开源工具的协同工作的成功案例,另一方面还因为它的分支管理机制。
这里我们只说 Git 作为版本控制的实践方式。
2. 两种版本控制方式
在 git 的使用过程中,假如团队中有多人协作,那么就涉及到一个版本管理的过程。目前,业内有两种版本协同过程,一种是每一个开发人员拥有自己的开发分支,另一种是每一个投产版本有一个开发分支,在完成开发测试过程后,把代码集中合并到投产分支上进行打包部署即可。后续迭代过程,再从投产分支上切出开发分支完成迭代或者把投产分支的代码合并到开发分支即可。
针对第一种,每一个开发人员都有一个单独属于自己的分支。这种实践方式大概是这样的:
- 最开始时,a 从投产分支上创建属于 a 的版本分支;
- b 从投产分支上创建属于 b 的版本分支;
- a、b 开发完成之后,依次登录发布到测试环境完成单元测试,这个过程中测试环境需要不断切换分支,测试环境会很不稳定,测试人员也无法立刻感知到 a 和 b 两个分支合并后的效果;
- 完成单元测试后,a 和 b 依次合并到投产分支上;
- 版本管理员或代码审核人员对 a 和 b 的代码进行 review 后合并分支;
- 合并完成后再次部署到测试环境上,此时测试环境上既有 a 的功能,又有 b 的功能,测试人员完成系统测试后投产;
- 假如其中一个开发人员的代码在生产环境中出现了问题,就需要回滚,只需要回滚有问题的开发人员的代码即可;
- 假如没有问题,下个版本迭代过程,就需要 a 和 b 都把这次投产分支上的代码合并到自己的分支上,然后再进行迭代开发;
- 优点:
解决功能点不同时投产问题
:如果不同开发人员的需求,可能不在同一个时间点上进行投产,采用这种方式,就可以让 a 开发人员先合并到投产分支进行投产,测试完 b 开发人员的代码后再合并进行投产;解决回滚问题
: 有时候代码需要进行回滚,这种方式可以只回滚有问题的开发人员的代码分支即可,不需要回滚全部的开发人员的代码;适用版本周期不稳定的团队
: 允许一个版本内,某一个功能点单独上线;
- 缺点:
测试环境拥堵
:由于测试时依赖测试环境,每一个开发人员开发完成后,都需要使用测试环境,这就造成了测试环境拥堵的现象,甚至会出现等待的现象;测试人员任务加重
:如果顺利完成单元测试,那么还需要对多个开发人员的版本分支进行合并,然后部署到测试环境上进行系统测试,测试人员的工作内容加大,即先进行每一个开发人员分支的单元测试,然后再进行多个开发人员的分支的合并后的系统测试;
针对第二种,每一个投产版本都设置一个开发分支。它的实践方式大概是这样的:
- 最开始时,版本管理员(或者团队某一个成员)在投产分支上创建出一个开发分支;
- a 和 b 都检出这个开发分支,并在这个分支上完成代码开发;
- 测试环境上也只需要部署这个分支就行了,测试人员只需要测试这个分支的代码即可;
- 所有的测试完成后,测试人员完成回归测试后,再合并到投产分支进行投产发布;
- 假如一个开发人员的代码在生产环境中出现了问题需要回滚代码,那么这个版本分支中的代码就需要全部回滚;
- 假如没有问题,那么下次版本人员直接在新的投产分支上切出新的开发分支即可;
- 优点:
测试环境不会拥堵
: 由于开发分支上既有 a 的代码,又有 b 的代码,所以同一个版本过程中,不会出现 a 和 b 拥堵的问题;能看到一个版本分支中不同功能的集成测试效果
:迭代周期较稳定
: 要求一个迭代周期内,所有的功能必须要要么都上线,要么都不上线;没有说可以一个功能点上线,一个遗留到下个迭代的情况;
- 缺点:
回滚范围过大
: 假如某一个开发人员的代码投产后有问题,需要回滚,那么就需要把整个版本内的所有人员的代码都需要回滚;可能会造成开发人员闲的闲,忙的忙
: 在一个版本周期内,假如一个开发人员效率很高,可能很快就完成人员,而另外一个开发人员的效率很低,需要到版本周期最后一天才完成,这就造成开发人员闲的闲忙的忙的后果;
3. 选择依据
这两种方式各有千秋,开发团队具体选择哪种控制方式,要根据具体情况具体分析。分析和选择的标准可能有以下几点:
- 团队规模的大小: 如果团队规模较大,一个版本的功能点较多,而团队分成多个小组分别负责不同的功能点,那么推荐使用第二种方式,因为这种方式可以为是每一个团队创建一个开发分支,一个投产版本内有多个不同开发分支,这种模型就优点类似于第一种了,只不过是为每一个团队分配一个代码分支;
- 系统的架构模型: 假如系统的架构模型是一种耦合度较低的系统架构,那么第一种方式会更适合一些,因为第一种模式更合适单打独斗;假如架构模型较为耦合,那么第二种可能会更适合一些,因为需要把集成测试的步骤提到前面;
- 测试资源的多少: 以开发人员上测试环境时不拥堵和测试人员不需要频繁切换分支为主,假如在有限的测试资源前提下,发生了拥堵,那么就应该尽量避免使用第一种方式;
- 版本周期的稳定与否: 假设版本周期确定后允许版本周期内,部分功能先上线,部分功能遗留到下个版本上线,那么可以选择第一种方式;假设版本周期确定后,所有功能必须全部同一时间上线,那么就可以选择第二种方式;
- 代码评审机制: 虽然 gitlab 可以让我们合并代码的时候完成代码评审,但是在选择这两种方式的同时,也需要考虑代码评审的时机和方式,如 gitlab 上只要发起了合并请求,版本管理人员就进行合并,代码评审就放到线下,评审通过之后才进行提交;或者在发起合并请求时就进行代码评审,如果代码评审通过,才允许进行合并;
4. 总结
第一种方式的适用场景:团队规模较小,开发人员适合单打独斗,版本周期要求不严格,代码评审不够规范等。嗯,是的,小公司的最佳实践方式。
第二种方式的适用场景: 团队规模较大,开发人员合作密切,版本周期要求严格,代码评审规范等。对,集团军作战的最佳实践方式。