发布分支

从开发者的角度讲,一个自由软件项目处于连续发布的状态。开发者通常一直在任何时候都运行最新的可用代码,因为他们需要定位bug,而且因为他们近距离的接触项目,可以避开当前特性的不稳定区域。他们通常会每天更新他们软件的备份,有时一天几次,当他们检入变更时,他们有道理认为其他开发者会在24小时内得到。

然而,何时项目应该做出正式的发布?是否仅仅取得某个时刻的快照,打包并交给世界,然后说“3.5.0”?常识告诉我们不是。首先,几乎没有一个时刻整个开发树是干净和准备好发布的。新开始的特性可能处于不同的状态。一些人可能检入了修正bug的主要变更,但是这个变更可能充满争议,在发生快照时依然处于辩论阶段。在这种情况下,仅仅是延后快照,等待辩论的结束是没有用的,因为此刻另一个不相关的辩论可能同时发生,那时你就需要等待那个辩论的结束。无法保证这个过程的终止。

在任何情况下,使用整个树的快照作为发布都会干扰正在进行的开发工作,即使整个树已经进入了可发布状态。假定快照将会成为“3.5.0”;而下个快照将会是“3.5.1”,会包含在3.5.0版本发现的大多数bug修正。但是如果快照来自同一个树,开发者在两个版本之间应该怎么做?他们不可以添加新特性;兼容性政策不允许这种行为。但是,不是每个人都会有激情修改3.5.0的代码bug。因为人们可能有需要完成的新特性,如果必须在静候和不想做的事情之间做出选择,他们会非常愤怒,而原因是项目发布过程要求开发树保持不自然的静默。

这个问题的解决方案一直是使用发布分支。一个发布分支仅仅是版本控制系统(见分支(branch))的一个分支,其中预定要发布的代码已经与开发主线分离。发布分支的概念不仅仅来自自由软件;许多商业开发组织也会使用它。然后,在商业环境中,发布分支通常被认为是昂贵的—一类正式的“最佳实践”可以在主开发线针对最终期限的同时,可以让团队的每个人分散精力去完成稳定主开发树的工作。

但是,发布分支在开源项目中是不可或缺的。我经历过的一些没有发布分支的项目,但是这样总会导致一些开发者必须停止下来等待别人—通常是微小的—发布出门的工作。在许多情况下通常结果是不好的。首先,整体开发动力被降低。其次,发布版本可能无法达到必须的质量,因为只有少数人在上面工作,而且他们会急于完成工作,这样别人才能回来工作。第三,通过设定了一个情形,不同类型的工作不必要的互相干扰了别人的工作,在心理上分割了开发团队。处于停滞的开发者可能会很乐意为发布分支贡献一些精力,只要他们可以根据自己的日程和兴趣做出选择。但是,没有这个分支,他们的选择就变成“今天我可以参与项目吗?”而不是“我可以为发布工作,还是为主开发线上的新特性的工作?”

发布分支的技巧

创建发布分支的确切技巧取决于你的版本控制系统,当然基本概念基本上是相同的。一个分支通常从另一个分支或主干分出。传统上,主干(trunk)是主要开发进行的地方,不受发布的限制。第一个发布分支,也就是将会变成“1.0”版本的分支是从主干分出的。在CVS中,分支命令类似下面的形式

$ cd trunk-working-copy
$ cvs tag -b RELEASE_1_0_X

或者在Subversion中,类似:

$ svn copy http://.../repos/trunk http://.../repos/branches/1.0.x

(这些例子都假设使用三部分的发布号码系统。因为我无法展示每个版本控制系统中的精确命令,我将会给出CVS和Subversion的例子,希望其他系统中对应的命令可以从中推导出来。)

请注意,我们创建了分支“1.0.x”(包含文字“x”),而不是“1.0.0”。这是因为同一条次要开发线—也就是同一个分支—将会被所有微小版本共用。用于发布的分支稳定化将会在本章后面的the section called “稳定发布版本”描述。这里,我们仅仅关注与版本控制系统的交互和发布过程。当发布分支已经稳定并做好准备,则应该从分支完成标记快照了:

$ cd RELEASE_1_0_X-working-copy
$ cvs tag RELEASE_1_0_0

$ svn copy http://.../repos/branches/1.0.x http://.../repos/tags/1.0.0

现在标签代表了项目源代码树在1.0.0版本的精确状态(在较老版本的打包发布和二进制程序被去掉后,如果某人希望获取时非常有用)。同一开发线的下个微小版本也很可能需要在1.0.x分支上准备,完成后,则增加1.0.1的标签。再次,重复完成1.0.2等等。当需要完成1.1.x版本时,则从主干再创建一个分支。

$ cd trunk-working-copy
$ cvs tag -b RELEASE_1_1_X

$ svn copy http://.../repos/trunk http://.../repos/branches/1.1.x

维护可以在1.0.x和1.1.x上并行继续,而版本发布也可以在两条线上独立进行。实际上,在两个不同的开发线上近乎同步的发布版本并不罕见。较旧的系列是保守的站点管理员应该使用的,他们可能不希望在没有小心准备的情况下做出重大的跳跃到(假设到)1.1。而同时,更多勇于冒险的人会将版本保持在最高的开发线上,以确保他们能获取最新的特性,即使要冒更大的稳定性风险。

这并不是唯一的发布分支策略,当然。在一些情况下,可能也不是最好的,只是在我参与过的项目中它的表现相当好。尽可以使用有效的策略,但请牢记要点:发布分支的目的是隔离发布工作与日常开发,并给项目一个物理实体用于组织整个发布过程。这个过程将会在下一小节详细描述。