版本控制的目的

如今软件行业中,版本控制软件的使用已经相当普及了,就算是个人项目,也会选择github这样的网站进行代码托管。回头想想,我们为什么要进行代码版本管理呢?软件版本控制的目的到底是什么?

1. 版本代码备份

想想没有版本控制软件的时代,如何进行历史版本代码的备份?我想大概是这样的。

.
├── tags
|   ├── v1.0.0.tar.gz
|   ├── v1.1.0.tar.gz
|   ├── v1.1.50.tar.gz
|   └── v1.2.0.tar.gz
└── trunk

每个版本节点,把最新版本的代码进行打包备份,仅仅是备份,我想这样是能满足需要的。但如果我们需要对历史版本进行修改,那会相当麻烦:要先对历史版本进行解压缩,解压之后进行代码修改,修改完成之后需要测试,完成之后再次进行打包备份。这种方法既不方便,又占空间,还容易出错。

下图是少三项目svn的tags目录,历史版本清晰明了,再也不需要打包与解压,复制与备份了。

少三1 svn tags

2. 版本回退

如果我们想要回到某个未备份的版本,比如策划C让我们改某个功能,等我们改完之后,策划C又让我们改回去。在没有版本控制软件的时代里,我们只能把这个功能按照原来的逻辑重写一次。

有了版本控制软件,我们可以找到自己及其他人在任何一次提交的代码,可以自由选择回退到任何历史版本。下图是我个人在少三项目4.2.0版本中骁勇榜开发过程中的提交记录,任何一个版本的修改内容都可以查看到,都可以恢复,再也不用担心策划的反悔了。

少三1个人 svn 提交记录

3. 多人合作开发

在没有版本控制软件的时代里,很难想想多人合作开发的过程,如果大家同时修改代码,想必每个人手中的代码都会不一样,这些代码如何合并到一个版本是一个极为复杂的工程。为了保证代码的一致性,必须确保同一时间只有一个人在同一个终端修改代码,这样的版本开发效率之低可想而知了。

而现在各种版本控制软件都支持多人合作开发,每个人只需要修改自己要改的代码,这些软件都提供很好的工具将你的修改提交进版本中,也能及时把他人修改的内容合并到自己的代码中。下图是少三2项目中最近的git提交记录,体现了多人合作开发的复杂与频繁。

少三2 git 提交历史记录

4. 问题回溯

假设我们的少三项目中没有版本控制软件,为了能够明确知道某段代码是谁创建的,谁在什么时间修改过什么内容,我们代码中的注释量将会比代码量还要多。

1
2
3
4
5
6
7
8
// user.go
// 20140415-1.2.0-武将光环系统-东东
// 20140428-1.2.50-神秘商店-廖廖
// 20140512-1.3.0-叛军系统-霸首
// 20140523-1.3.50-武将图鉴-随风
type User struct {
    //...
}

有了SVN之后,我们可以很方便的找出哪个文件什么时间谁改过什么内容,这对于历史问题的排查非常有用,否则只能靠猜了。下图是少三项目项目初期的部分svn记录,当然,少三项目初期svn commit的注释确实很不规范,某位同学竟然不写注释提交代码(很不好的习惯),这在项目后期是绝对不允许的。

少三1 user 文件的提交记录

少三1 svn 提交文件列表

下图的提交记录就正规很多了,土八路进化为正规军了。

少三1后期 svn 提交记录

5. 多分支并行开发

多分支并行开发在传统软件行业应该是一件很正常的事情,在游戏行业也比较常见,在少年系列项目中,不是特别多,我们在版本规划时就尽量避免多分支并行开发。因为游戏项目的二进制资源很多,多分支并行开发时,必然会面临版本合并的工作,这些二进制文件在合并时会面临比较大的挑战。多分支并行开发的情况也不是完全没有,比如某些特大功能,不能按照正常版本进度开发时,就需要拉分支与正常版本并行开发。我相信,没有版本控制软件的帮助,多分支并行开发绝对是一件不可能完成的任务。

下图是少三2项目最近的几个branches,并行开发的情况还是不可避免的,尤其是历史bug,需要修复到历史的所有版本。

少三2 git branches

版控工具

1. SVN

SVN的特点

使用统一的中央仓库对文件进行集中式的管理。

SVN的优点

操作简单,学习成本低。 能对文件进行权限控制。

SVN的缺点

在没有网络的情况下就不能对文件进行版本控制操作。

SVN的适用场景

有权限控制的代码开发(即不是每个人都可以看到项目中的所有代码)和软件文档的管理。

2. Git

Git的特点

既能集中式又能分布式地管理文件。Git的集中式管理模式和SVN的一样,它的分布式管理模式是每个开发人员都要自己维护一个与中央仓库关联的本地仓库。

Git的优点

分布式管理,数据不易丢失。因为每个客户端上都持有一个与中央仓库一样的本地仓库,所以当中央仓库的数据丢失时,可以从任意一个客户端上获取数据进行恢复。

支持离线版本控制。在没有网络的时候,开发人员可以使用本地仓库进行版本控制操作,待有网后,再将改变的内容推送到中央服务器。

支持现场版本控制。例如:产品部署在客户那边,出了Bug,需要去现场进行修复。如果我们使用的是SVN,我们需要将修改完的代码拷贝回来,然后复制粘贴进工程,最后再与SVN进行同步。反之,如果我们使用的是Git,我们只需要在工程的目录下初始化Git,然后修正Bug,最后再打个补丁把补丁带回去就行了。

服务器压力小。因为使用SVN的开发人员会一直连着服务器进行操作,但是使用Git的开发人员可能是一周甚至一个月才与服务器进行交互,所以SVN服务器承受的访问量与数据量要比Git服务器大很多。

支持补丁技术。任意两个开发人员可以通过补丁来整合代码,整合过程不通过中央服务器。

Git的响应速度比SVN快。

Git的缺点

学习成本高。因为需要学习很多的操作指令。

不能对文件进行权限控制。因为Git使用分布式管理,所以每个客户端就会持有与中央服务器一样的仓库,拥有了一样的仓库就拥有了中央仓库上所有的代码。

Git的适用场景

无权限控制的代码开发。

3. P4(perforce)

P4的特点

Perforce是一款构建于可伸缩客户/服务器结构之上的软件配置管理工具。

P4的优点

灵活的客户端视图。

对权限控制的比较细,适合公司开发。

在服务器上跟踪你的工作副本,大型工作副本处理速度更快。

分支机制及冲突解决工具更好。

二进制安全,适合管理大量美术资源。

P4的缺点

收费软件,使用成本很高。

使用起来很原始,提交流程很复杂。

P4的适用场景

大量资源文件的版本管理工作。

相信广大程序猿对于SVN和Git都是比较熟悉的,项目中SVN的使用率最高;而Git才是程序猿的最爱,多分支开发和代码合并操作相比SVN要方便太多;P4最近常被美术同事提起,个人及团队确实没用过,只能在网上查了很多资料才有这些总结,也许很多结论不够准确,但适用场景应该不假,就是适合大量资源文件的版本管理工作,SVN下面的美术资源更新真的很恐怖,Git下面二进制文件冲突了也很抓狂。

常规软件版本分支

truck(主分支):是用来做主方向开发的,新功能的开发应放在主分支中,当模块开发完成后,需要修改,就用branch。

branch(分支):分支开发和主分支开发是可以同时进行的,也就是并行开发,分支通常用于修复bug时使用。

tag(标记):用于标记某个可用的版本,可以标记已经上线发布的版本,也可以标记正在测试的版本,通常是只读的。

这套逻辑来自于SVN,Git也基本适用,Git默认的主干为master,其他是一样的。

手游开发中的版本控制

1. 版控软件的选择(git or svn ?)

我相信每个项目组决定用什么版本控制软件的时候,都会有一次争执,到底是用git还是svn?我所经历的游戏项目,都是以SVN作为核心版本控制软件,周边一些框架与工具或者文档会以Git作为版本控制软件。作为程序猿来说,确实会更喜欢Git一些,原因在于一些开源项目多存于github上,个人项目也会选择github等基于Git做版本控制的代码托管平台。那为什么公司内的项目大多都是SVN呢,主要原因有两个,一是Git操作成本偏高,策划美术等职能同学不喜欢;另一个是Git的权限控制太简单,没有办法按照职能分配目录权限。我们新项目在版控软件的选择上也经过了一番battle,最终还是无奈地选择了SVN,作为程序猿的我真的很无奈啊。

2. 分支管理

每个项目都有自己的分支管理办法,但手游项目属于中小型项目,属于敏捷开发型项目,开发节奏较快,开发周期没有传统软件行业那么长。少年工作室的项目版本开发周期基本维持在一个月一个大版本,半个月一个优化版本的频率,公司内其他项目组也有更快的周更节奏。开发节奏快,就意味着版本分支多,甚至有多分支同时开发的可能。因此,分支管理是否合理,会影响到版本开发效率与质量。

下图为少年工作室分支管理规范,目前所有项目基本都是按照这个规范在进行管理。

少年工作室分支管理规范

3. 开发流程

主分支开发

大部分情况下,我们都在主分支(trunk)上进行版本开发,开发并测试完成之后拉取开发分支(branch),并以分支版本进行版本发布。

分支开发

在部分特殊情况下,比如下个版本内容量较大,开发时间比较长的情况下,会选择将优化版本放在分支中进行,主分支同步进行下个版本的开发。在分支开发的优化版本在版本完成并上线后,需要统一合并到主分支,这种情况可能会存在漏合代码的情况,需要小心谨慎一些,并在主分支测试时同步测试这些优化内容。

bug修复流程

bug修复主要是指线上版本的bug修复,通常是优先在分支进行修复,测试并上线后需要将修复代码合并到主分支,如果是历史版本中存在的bug,还需要合并到存在bug的历史分支,这一步也很重要,如果有遗漏则会造成海外版本存在未修复的bug。

结语

项目中到底应该怎样管理分支,开发流程的规划都要适合自己的项目,没有最好的方案(理想中还是有最优方案的),只有最合适的方案。之前公司内也有其他项目组介绍过更好的管理方法,但我们一致觉得不适合我们的项目,或者在我们这边执行会存在一些问题,因此我们坚持了从少三积累到现在的这套流程规范。当然你如果对我们的方案有疑问或者有更好的方案,欢迎一起研究探讨。

少年码上记-微信公众号