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.

标签

另一个常见的版本控制概念是标签. 标签是项目的一个 快照, 它在 Subversion 中到处都是, 因为每一个版本号都对应着提交后, 文件系统的 一个快照.

然而, 用户经常想给标签取一个更人性化的名字, 例如 release-1.0 , 而且用户只想对文件系统的某个子目录做快照, 毕竟人们更容易记住 项目的发布版 1.0 是版本号为 4822 的特定子目录.

创建简单的标签

创建标签的命令是 svn copy. 如果用户想为 处于 HEAD/calc/trunk 创建一个快照, 就执行:

$ svn copy http://svn.example.com/repos/calc/trunk \
           http://svn.example.com/repos/calc/tags/release-1.0 \
           -m "Tagging the 1.0 release of the 'calc' project."

Committed revision 902.

这个例子假设目录 /calc/tags 已经存在 (如果不 存在, 就先用 svn mkdir 创建它). 复制完成后, 新目录 release-1.0 就成为了 /calc/trunk 在复制那一刻的永久快照. 当然, 用户也 可以指定被复制的版本号, 避免其他在用户没有觉察的时候, 向仓库提交了新 的修改. 如果说用户已经知道版本号为 901 的 /calc/trunk 正是自己想要的快照, 就给命令 svn copy 添加选项 -r 901.

请等一下, 这和创建分支的步骤不是一样的吗? 事实上的确如此. 对于 Subversion 而言, 标签和分支没有区别, 它们都是通过命令 svn copy 创建的目录. 之所以把复制出的目录叫作 标签 的唯一原因是 用户 已经决定把该目录看成 标签—只要没有人往标签提交修改, 它就永远保持创建时的样子. 如果用户 在创建标签后, 往标签提交了新的修改, 那么从用户的角度来看, 它就变成了 一个分支.

如果读者是仓库的管理员, 那么你有 2 种标签管理方法. 第 1 种是 放任不管: 作为一种项目管理策略, 一开始便规定好标签 的存放位置, 确保所有用户都知道如何对待他们复制的目录 (也就是确保他们不 会向标签提交修改). 第 2 种更具有强制性: 使用和 Subversion 配合的 访问控制脚本, 禁止任何人在标签区提交修改, 除了创建新的标签 (见 第 6 章 服务器配置). 第 2 种方法通常是没有必要的, 因 为如果用户不小心向标签提交了修改, 总是可以用之前介绍的方法, 撤消已经 提交的修改.

创建复杂的标签

有时候, 用户可能需要更复杂的 快照, 它不仅仅是单独 版本号下的单个目录.

举个例子, 假设你的项目比我们的 calc 庞大得 多: 项目内包含了大量的文件与目录. 在工作过程中, 你可能需要创建一个 含有指定特性和问题修正的工作副本, 创建的方式可以是选择性地把文件或 目录退回到指定的版本 (使用带有选项 -rsvn update 命令), 把文件和目录切换到特定的分支 (通过命令 svn switch), 甚至是一连串的本地修改. 创建完毕后, 你的工作副本就变成了一个大杂烩, 但是在测试后, 你确定这 正是你想要创建标签的目标.

是时候创建快照了, 但复制 URL 在这里不起作用. 对于这种情况, 用户 想要的是在仓库中, 为当前状态下的工作副本创建一个快照. 幸运的是 svn copy 的 4 种用法中 (见 svn 参考手册—Subversion 命令行客户端svn copy (cp)), 包含了把工作副本复制到仓库中的能力:

$ ls
my-working-copy/

$ svn copy my-working-copy \
           http://svn.example.com/repos/calc/tags/mytag \
           -m "Tag my existing working copy state."

Committed revision 940.

现在, 仓库中就出现了一个新目录 /calc/tags/mytag , 它是当前工作副本的快照—混合的版本号, URL, 本地修改 等.

有些用户已经发现了这个特性的其他一些用法. 有时候用户的工作副本 可能包含了一堆本地修改, 他想让其他用户审查一下, 但这次不是用 svn diff 生成并发送补丁 (svn diff 无法体现目录或符号链接的变化), 而是用 svn copy 把 当前状态下的工作副本 上传 到仓库中的适当位置, 例如你的 私有目录, 然后其他用户就可以用 svn checkout 逐字 拷贝你的工作副本, 或者用 svn merge 接收你做出的修改.

虽然这是上传工作副本快照的好办法, 但要注意的是这 不是 一个创建分支的好办法, 创建分支应该是它本身的事件, 而这种 方法创建的分支混合了额外的修改, 分支的创建和修改都在一个单独的版本号 里, 这样的话我们以后就难确定哪一个版本号才是分支点.