分支/标记

版本控制系统的一个特性是能够把各种修改分离出来放在一个单独的开发线上。这条线被称为分支。分支经常被用来试验新的特性,而不会干扰正在修改编译器错误和 bug 的主开发线。当新的特性足够稳定之后,开发分支就可以合并回主分支里(主干).

版本控制系统的另一个特性是能够标记特殊的版本(例如一个发布版本),所以你可以在任何时候重新建立一个特定的构建或环境。这个过程被称作标记

Subversion 没有用于建立分支和标记的特殊命令,但是使用所谓的便宜复制来代替。便宜复制类似于 Unix 里的硬连接,它意思是代替一个版本库里的完整的复制,创建一个内部的链接,指向一个具体的版本树。结果分支和标记迅速被创建,并且几乎没有在版本库里占据任何额外的空间。

创建一个分支或标记

如果你用推荐的目录结构导入了一个工程,那么创建分支或标记就非常简单:

图 4.52. 分支/标记对话框

分支/标记对话框


在你当前的工作副本中选择你想要复制的分支或标记的目录,然后选择命令TortoiseSVN分支/标记...

The default destination URL for the new branch will be the source URL on which your working copy is based. You will need to edit that URL to the new path for your branch/tag. So instead of

http://svn.collab.net/repos/ProjectName/trunk
      

you might now use something like

http://svn.collab.net/repos/ProjectName/tags/Release_1.10
      

If you can't remember the naming convention you used last time, click the button on the right to open the repository browser so you can view the existing repository structure.

intermediate folders

When you specify the target URL, all the folders up to the last one must already exist or you will get an error message. In the above example, the URL http://svn.collab.net/repos/ProjectName/tags/ must exist to create the Release_1.10 tag.

However if you want to create a branch/tag to an URL that has intermediate folders that don't exist yet you can check the option Create intermediate folders at the bottom of the dialog. If that option is activated, all intermediate folders are automatically created.

Note that this option is disabled by default to avoid typos. For example, if you typed the target URL as http://svn.collab.net/repos/ProjectName/Tags/Release_1.10 instead of http://svn.collab.net/repos/ProjectName/tags/Release_1.10, you would get an error with the option disabled, but with the option enabled a folder Tags would be automatically created, and you would end up with a folder Tags and a folder tags.

现在你需要选择从哪里复制。这里你有三个选择:

版本库中的最新版本

新的分支从最新版本复制到版本库中。没有数据需要从你的工作副本传递到版本库,而且分支非常迅速的被创建。

版本库中指定的版本

新的分支从你选选择的旧版本复制到版本库中。当你忘记为上一周发布的项目创建标记时,这就很有用了。如果你不记得版本号,点击右边的按钮来显示版本日志,然后从中选择版本号。也没有数据需要从你的工作副本传递到版本库,而且分支非常迅速的被创建。

工作副本

新的分支是与你本地工作副本一模一样的副本。如果你将工作副本中某些文件更新到某个早先的版本,或者你进行了本地修改,这些正是要进入副本的。当然,这些繁多的标记会作为传输数据从你的工作副本送回版本库,如果它们不存在于版本库中。

如果想要将工作副本自动切换到新创建分支,选中切换工作副本至新分支/标记复选框。但是如果你要这样做,首先确认你的工作副本中不包含修改。如果有,这些修改将会在你切换时合并到分支的工作副本中。

If your working copy has other projects included with svn:externals properties, those externals will be listed at the bottom of the branch/tag dialog. For each external, the target path and the source URL is shown.

If you want to make sure that the new tag always is in a consistent state, check all the externals to have their revisions pinned. If you don't check the externals and those externals point to a HEAD revision which might change in the future, checking out the new tag will check out that HEAD revision of the external and your tag might not compile anymore. So it's always a good idea to set the externals to an explicit revision when creating a tag.

The externals are automatically pinned to either the current HEAD revision or the working copy BASE revision, depending on the source of the branch/tag:

表 4.1. Pinned Revision

Copy SourcePinned Revision
版本库中的最新版本external's repos HEAD revision
指定版本库中的版本external's repos HEAD revision
工作副本external's WC BASE revision


externals within externals

If a project that is included as an external has itself included externals, then those will not be tagged! Only externals that are direct children can be tagged.

按下确认提交新副本到版本库中。别忘了提供一条日志信息。需要注意的是这个副本是在版本库内部创建的。

需要注意除非你决定切换工作副本到新创建分支,建立一个分支或标记不会影响你的工作副本。即使你从工作副本创建分支,这些修改也会提交到新分支里,而不是到主干里,所以你的工作副本可能仍然标记为已修改状态来避免影响主干。

创建分支或标记的其他方法

你可以在没有工作副本的情况下创建分支或标记。要这样做,打开版本库浏览器。你可以拖拽文件夹到新的位置。要创建副本,你必须在拖拽过程中按下 Ctrl 键,否则文件夹是被移动,不是被复制。

你可以使用鼠标右键拖拽文件夹。一旦你松开鼠标右键,你可以从右键菜单中选择移动或复制文件夹。当然,要创建分支或标记你必须复制文件夹,而不是移动它。

还有一个方法就是从日志对话框。你可以显示某个文件夹,例如 trunk,的日志对话框,选择一个版本(可以是位于顶端的最新版本,也可以是先前的版本),右键单击并选择从版本创建分支/标记

检出或者切换

...这是个小问题。当从版本库中预期的分支检出所有数据到你的工作副本目录时,TortoiseSVN切换... 仅仅传输已经被修改的数据到你的工作副本中。有利于减轻网络负担,也有利于你的耐心。 :-)

为了能够使用你最新产生的副本或标记,你可以采用下面几种方法。你可以:

  • TortoiseSVN检出一个最新的工作副本在一个空目录下。你可以在你的本地磁盘上的任意位置进行检出操作,同时你可以从版本库中按照你的意愿建立出任意数量的工作副本。

  • 将你当前的工作副本切换到在版本库中新建立的副本。再一次选择你的项目所处的顶级文件夹然后在右键菜单中使用TortoiseSVN切换...

    在接下来的对话框中输入你刚才建立的分支的 URL。选择最新版本单选按钮然后确认。你的工作副本就切换到了最新的分支/标记。

    切换操作起来就象更新,因为它没有丢弃你在本地做的修改。当你进行切换的时候,工作副本里任何没有提交过的修改都会被合并。如果你不想看到这样的结果,那么你可以有两种选择,要么在切换前提交修改,要么把工作副本恢复到一个已经提交过的版本(通常是最新版本)。

  • 如果你需要在主干和分支上工作,但是又不想耗费资源来进行一个全新的检出操作,你可以使用 Windows 资源管理器来将你的主干工作副本复制到另一个文件夹,然后使用TortoiseSVN切换...这样就会复制新的分支。

图 4.53. 切换对话框

切换对话框


尽管 Subversion 本身不区分标记和分支,但它们通常被应用的场合还是有些不同。

  • 标记被用来建立一个项目在某个特殊的阶段的静态映像。通常情况下他们本不是用来进行开发的 - 分支是用来进行开发的,这就是我们推荐 /trunk /branches /tags 这样的版本库结构的原因。在标记上工作并不是一个好想法,因为你的本地文件没有写保护,没有什么办法防止你误操作。然而,如果你试着提交一个包含 /tags/ 的路径到版本库,TortoiseSVN 会警告你。

  • 如果你需要在一个已经标记的发布版上做更多的修改。正确的操作方法是先从标记处建立一个新分支然后提交这个分支。在这个分支的基础上进行修改后再从这个新分支上建立一个新标记,例如 Version_1.0.1

  • 如果你修改了一个从分支建立的工作副本然后又提交了这个副本,那么所有的修改会转到一个新分支里而不是 主干。仅仅是存储了修改的数据。其余的数据还是便宜复制。