全部博文(465)
分类: IT业界
2012-07-04 17:29:55
用分支实现交迭
是不是发布补丁版本这个词听起来比交迭这个词更熟悉一些?发布补丁版本是交迭的一种。让我们从这里开始谈起。
绘图产品SuperPen 1.0版,经过六个月的开发,终于上市!在大笔捞钱的同时,公司正在组织开发2.0版,引入更炫的功能,卖出更好的价钱!研发团队全体,继续日夜奋战。在一派大好形势下也有些不和谐的声音,一些用户抱怨,1.0版里有这个Bug、那个Bug……虽然公司解释,这些都会在2.0版里修复,2.0版会以优惠的价格卖给老用户。但是,有的用户坚持认为,应该免费提供对1.0版中的Bug的修复,并且现在就要提供,等不到三个月后2.0版啦。“好吧,好吧,”公司管理层决定,“我们出个1.1版,只包括对1.0版中的Bug的修复,不包括任何新功能。把1.1版免费发放给购买了1.0版的老用户。他们可别想趁机占便宜,得到2.0版里的新功能。”
开会回来,研发经理犯了难。“2.0版的研发工作都开始了一个多月了。已经为实现新功能做了很多新的修改。难道这些都作废,退到1.0版从头来?”配置管理工程师却胸有成竹,“头儿,我们用那种叫分支的方法,就可以实现1.1版和2.0版同时开发,哪个也不耽误。”
没错,现在是分支大显身手的时候了。先考查一下现在的情形:主干上比较古老的部分,是目标为1.0版的研发;主干上某一点,是1.0版本发布了。随后,主干上开始了目标为2.0版的研发,现在正在向前演进。
为支持1.1版,我们从主干上1.0版本发布对应的那一点起,做一个分支,岔出来。这条分支的目标是1.1版,也可能将来1.2版也在这上面。我们把这条分支命名为1.x。在这条分支上,我们修复1.0版用户发现的各个Bug。一个又一个关于Bug修复的变更集被提交到这条分支上。分支在向前演进。在经历了若干次集成、测试之后,1.1版在这条分支上正式发布!
把1.1版称做补丁版本(Patch Release),是因为1.1版跟1.0版相比,没有什么大的变化,主要是一些修修补补。注意补丁还有另外一个含义,不完整的发布。比如说,安装某软件,在用100MB的安装包安装后,再安装一个2MB的汉化补丁,把该软件的菜单都改成方块儿字。这个意义上的补丁,不是这里讨论的主题。
复用另一条分支上的改动
为1.1版所做的工作和为 2.0版所做的工作,其工作目的不同,其代码修改不同,因此用两条分支来体现。然而,为什么一定要用分支的方式来实现,而不是用完全独立的两个目录或两个版本库来实现呢?主要原因是,分支除了有隔离的功能外,还对共享有比较好的支持。使用分支,便于彼此同步和复用。
理想的情形是,在1.x分支上,从1.0版起到1.1版之间所有的代码改动,都应该拿到主干上,贡献给2.0版。对于这种情形,可以使用版本控制工具提供的简单命令,一股脑儿地把改动从1.x分支合并到主干上来。
以上说的是理想的情形,1.x分支上的全部改动都应该拿到主干上。在实际项目中,并不是这么理想的情况。比如有个Bug,在1.1版上的修复,只是临时性的修复,治标不治本,因为治本的代价太大,需要改动软件中的一些底层结构。而在2.0版中,软件的相关底层结构已经优化,因此,这个Bug在2.0版中已经不存在了。
对此,比较保险的解决办法是,对1.x分支上的每一个变更集,均由开发人员做出判断,是否适合合并到主干。挑挑拣拣,合适的拿,不合适的不拿。
这是以变更集为基础的挑选工作。而在有些团队里,使用的是以变更请求条目为基础的挑选工作。这里的变更请求主要是缺陷修复请求,可能还有少量增强请求。考查所有目标为1.x分支的变更请求,看看是否同样适用于主干。如果适合,就把相应的变更集从1.x分支复制到主干。
有选择地合并比较保险,但其管理成本也是显然的。在有些项目中,大家宁可容忍把没必要合并的改动合并过来,也不愿花费可观的精力去把需要合并的改动挑出来。于是就会使用把1.x分支上的所有改动都拿过来这样的合并方法,就好像工作在理想情况下。
上面讨论的都是从1.x分支到主干的合并。可能还存在相反方向的合并。比如,如果由于某种原因,一个缺陷先在主干上修复了。不久又决定要在1.x分支上使用同样的方式修复该缺陷。这时,就需要个案处理,把对应的变更集从主干复制到1.x分支上。注意这个方向上的合并不应该成为主流,两边都有的缺陷通常应该在1.x分支上先修复,因为1.x分支邻近发布,对缺陷修复的需求更紧急。
不论是以上哪种合并方法,执行合并操作时,一般来说,大部分改动可以自动合并到另一个分支上。当然,合并可能产生冲突,比如说某个文件在两个分支上都改动了同一行,且改为不同的内容。这就需要人来解决,懂得源代码语义的人来解决。如果合并是由集成工程师或配置管理工程师主导的,那么出现合并冲突时,一定要找相关开发人员来解决,不要自己改代码。
除了代码合并冲突,还可能在编译时或运行时出现问题。这些问题的本质原因都是,在一条分支上的代码修改,是以当时这条分支上的源代码为基础的修改,它不一定适合放在另一条分支的末端的源代码上。如果这样的问题经常冒出来,严重干扰了目标分支上的代码质量,那么就要考虑先对合并过来的改动进行一定的质量保证工作,再最终提交到目标分支。而如果这类问题不多,那么依靠在目标分支上的(狭义)集成中或集成后的质量保证工作来发现和解决问题就可以了。
什么时候问题不多,什么时候问题多?一般来说,新的分支刚创建的时候问题不多,因为两个分支上的内容差不多。随着时间的流逝,两个分支上的内容相差越来越多,这时候把一个变更集从一个分支复制到另一个分支,就会越困难,出现各种问题的可能性就越大。可能需要因此而调整合并的策略,引入更多的检查。
关于不同分支间合并,还要注意合并的频率。如果合并工作一直拖着,过了很久之后积攒下大量的合并一起做,那么合并就会变成一件头疼的事。一团乱麻,出了问题不好解决。这也是因为大家已经对很久以前的改动不熟悉了,需要更多的时间回忆起来。可以考虑制定流程,每当提交一个变更集到1.x分支后,就要考查是否应该把它合并到主干。当然,定期地合并也不错,只要两次合并的间隔不要太久。
我们这里谈论的分支,可以是广义上的分支的不同具体形式:可以是狭义的分支,也可以是分布式版本控制工具中的不同的版本库,或者其他的方法。只要这些方法能够方便地做到不同(广义)分支之间的隔离和共享就可以。
本文节选自《未雨绸缪——理解软件配置管理(第2版)》
董越著
图书详细信息:http://blog.chinaunix.net/space.php?uid=13164110&do=blog&id=3254256