本文档正在编写中,内容可能随时更改,可能无法准确描述 Apache™ Subversion® 软件的任何已发布版本。将此页面添加为书签或向他人推荐此页面可能不是一个明智的选择。请访问 https://svnbook.subversion.org.cn/ 查看本书的稳定版本。

常见分支模式

分支和 svn merge 有许多不同的用途,本节将介绍最常见的用途。

版本控制最常用于软件开发,因此这里简要介绍了程序员团队使用的两种最常见的分支/合并模式。如果您没有将 Subversion 用于软件开发,可以跳过本节。如果您是第一次使用版本控制的软件开发人员,请密切注意,因为这些模式通常被经验丰富的开发者认为是最佳实践。这些流程并不特定于 Subversion;它们适用于任何版本控制系统。尽管如此,从 Subversion 的角度来了解这些流程可能会有所帮助。

发布分支

大多数软件都有一个典型的生命周期:编码、测试、发布、重复。这个流程有两个问题。首先,开发人员需要在质量保证团队花费时间测试看似稳定的软件版本的同时,不断编写新的功能。新的工作不能在软件测试期间停止。其次,团队几乎总是需要支持旧的已发布软件版本;如果在最新代码中发现错误,则该错误很可能也存在于已发布的版本中,客户会希望获得错误修复,而无需等待主要的新版本发布。

这就是版本控制可以提供帮助的地方。典型的流程如下所示

  1. 开发人员将所有新工作提交到主干。日常更改被提交到 /trunk:新功能、错误修复等。

  2. 主干被复制到一个名为“发布”的分支。当团队认为软件已准备好发布时(例如,1.0 版本),/trunk 可能会被复制到 /branches/1.0

  3. 团队继续并行工作。一个团队开始对发布分支进行严格的测试,而另一个团队继续在 /trunk 上进行新工作(例如,用于 2.0 版本)。如果在任一位置发现错误,则根据需要将修复从一个位置挑选到另一个位置。然而,在某个时刻,即使这个过程也会停止。该分支在发布前被“冻结”以进行最终测试。

  4. 该分支被标记并发布。当测试完成后,/branches/1.0 被复制到 /tags/1.0.0 作为参考快照。该标签被打包并发布给客户。

  5. 该分支随着时间的推移而维护。虽然 2.0 版本的工作继续在 /trunk 上进行,但错误修复继续从 /trunk 移植到 /branches/1.0。当积累足够的错误修复时,管理层可能会决定发布 1.0.1 版本:/branches/1.0 被复制到 /tags/1.0.1,该标签被打包并发布。

随着软件的成熟,整个过程会重复:当 2.0 工作完成后,会创建一个新的 2.0 发布分支,进行测试、标记,并最终发布。经过几年后,存储库最终会拥有多个处于“维护”模式的发布分支,以及代表最终发布版本的多个标签。

功能分支

一个功能分支是一种分支,它在本节中一直是主要示例(您一直在 Sally 继续在 /trunk 上工作的同时进行操作)。它是为了在不影响 /trunk 的稳定性的情况下处理复杂变更而创建的临时分支。与发布分支(可能需要永远维护)不同,功能分支是有生之年,被使用一段时间,合并回主干,最后被删除。它们的使用寿命是有限的。

同样,项目策略在何时创建功能分支方面存在很大差异。有些项目根本不使用功能分支:对 /trunk 的提交是自由的。这种系统的好处是简单易行——没有人需要学习分支或合并。缺点是主干代码经常不稳定或无法使用。其他项目则极端地使用分支:决不直接将更改提交到主干。即使是最微不足道的更改也需要在短暂的分支上创建、仔细审查,然后合并到主干。然后删除该分支。这种系统保证了始终拥有一个非常稳定和可用的主干,但代价是巨大的流程开销。

大多数项目采用折中的方法。他们通常坚持要求 /trunk 在任何时候都能编译并通过回归测试。只有当更改需要大量不稳定提交时,才需要功能分支。一个经验法则是提出以下问题:如果开发人员孤立地工作几天,然后一次性提交了大型更改(这样 /trunk 永远不会变得不稳定),那么这是否是一个太大的更改需要审查?如果对该问题的回答是“是”,则应在功能分支上开发更改。当开发人员向该分支提交增量更改时,这些更改可以轻松地由同行进行审查。

最后,还存在一个问题,即如何最好地使功能分支在工作过程中与主干保持“同步”。正如我们之前提到的,在分支上工作数周或数月存在很大风险;主干更改可能会不断涌入,以至于两条开发线之间差异如此之大,以至于尝试将分支合并回主干可能会变成一场噩梦。

这种情况可以通过定期从主干到分支运行自动合并来避免。制定一个策略:每周一次,将过去一周的全部主干更改合并到该分支。

当您最终准备将“同步”后的功能分支合并回主干时,首先从主干到分支进行最终的自动合并,以获取最新的主干更改。完成此操作后,分支和主干的最新版本将绝对相同,只是您的分支更改除外。然后,您可以从分支到主干运行自动重新集成合并

$ cd trunk-working-copy

$ svn update
Updating '.':
At revision 1910.

$ svn merge ^/calc/branches/mybranch
--- Merging differences between repository URLs into '.':
U    real.c
U    integer.c
A    newdirectory
A    newdirectory/newfile
 U   .
…

另一种思考这种模式的方法是,您每周将主干同步到分支类似于在工作副本中运行 svn update,而最终的合并步骤类似于从工作副本中运行 svn commit。毕竟,工作副本除了是一个非常浅层的私有分支之外,还能是什么呢?它是一个只能存储一次更改的分支。

TortoiseSVN 官方中文版 1.14.7 发布