This text is a work in progress—highly subject to change—and may not accurately describe any released version of the Apache™ Subversion® software. Bookmarking or otherwise referring others to this page is probably not such a smart idea. Please visit http://www.svnbook.com/ for stable versions of this book.

常见的分支模式

分支和 svn merge 有着非常丰富的用法, 本节介绍 其中最常见的几种.

版本控制最经常用在软件开发领域, 所以本节先介绍 2 种在开发人员中最 常见的分支/合并模式. 如果读者使用 Subversion 不是为了软件开发, 尽管跳过 本节, 如果你是第一次使用版本控制工具的软件开发人员, 请集中注意力, 因为 这些模式经常被经验丰富的程序员看成是最佳的做法. 本节的内容不仅限于 Subversion, 它们同样适用于其他版本控制系统, 使用 Subversion 的术语进行 描述更有助于用户理解.

发布分支

大多数软件都有一个典型的生命周期: 编码, 测试, 发布, 如此循环往复. 这个过程有两个问题. 首先开发人员需要不断地往软件添加新特性, 同时质保 团队也会不断地测试稳定版, 开发与测试是同时进行的. 第二, 开发团队通常 需要支持已发布的旧版, 如果在最新版发现了一个问题, 那么旧的发布版很 可能也有同样的问题, 客户更希望直接修复这个问题, 而不是等待新的版本发 布.

版本控制工具可以帮助开发人员解决这些问题, 典型的步骤是:

  1. 开发人员把所有的新工作都提交到主干上. 把 每天的修改—包含新特性, 问题修复等—都提交到 /trunk.

  2. 复制主干到 发布 分支. 如果团队认为软件已经准备好发布 (例如发布版 1.0), 可能会复制 /trunk/branches/1.0.

  3. 团队继续并行工作. 一个团队开始对发布分支 进行严格的测试, 其他团队继续在 /trunk 上开发 新的工作 (例如版本 2.0). 如果有问题出现 (无论是在 /trunk, 还是发布分支), 修复问题, 并把修改精选到拥有 相同问题的分支上. 但是这个过程有时候也会停下来, 例如为了发布前的 最终测试而 冻结 分支.

  4. 为分支打标签并发布. 当测试结束, /branches/1.0 被复制到 /tags/1.0.0 , 标签被打包并交付给客户.

  5. 继续维护分支. 当团队在主干上为版本 2.0 工作时, 修复问题的修改从 /trunk 回植到 /branches/1.0. 如果修改积累得足够多了, 团队 可能决定发布 1.0.1: /branches/1.0 被复制到 /tags/1.0.1, 标签被打包并交付给客户.

整体过程随着软件的成长而不断重复: 当版本 2.0 完成时, 创建了一个新 的 2.0 发布分支, 再对该分支进行测试, 打标签并发布. 几年后, 仓库拥有 了大量的处于 维护 状态的发布分支, 以及代表了最终交付 版的标签.

特性分支

特性分支 (feature branch) 是分支的一种类型, 它曾是本章的主要例子 (在这个例子中, 你在分支上工作, 而 Sally 在 /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. 毕竟, 工作副本就像是 一个非常浅的私有分支, 一次只能保存一个修改.