分支,标签,与合并几乎是所有版本控制系统的基本概念.如果你不熟悉这些功能,我们在这章提供了一个很好
的介绍.如果你非常熟悉了,也能很好的让你看看Subversion是如何实现这些功能的.
分支是版本控制的一项基本的功能.如果你将要使用Subversion来管理你的数据.这是一个特色你将最终依赖
它.这章要求你已经对Subversion的基本概念比较熟悉.

什么是分支?
假设你需要在你的电脑上维护一份被分离的文档,一个手册或是别的什么.某天要求你对同份文档做一个不同
的修改分离,但分离后他们两者只有一小部分不同,因此只有轻微的不同.
你将怎么解决这种处境?显而易见的方法是不是:可以再拷贝这份文档,然后保存两个不同的分离版本.当某个
部分要进行修改时,只要写入对应的文件就可以了.
经常需要对两个拷贝版本进行同样的修改.例如:如果发现一个打印错误在第一个文件里,这也很可能存在第二
个拷贝文件里.这两个文件是相同的的.
这就是分支的基本概念,一条基于另外一条开发线存在的分支.并共享在分离之前的日志.一个分支就象一个拷
贝的存在,并从那里离开,并具有自己的历史.
图:Figur 4.1. Branches of development
Subversion提供了一些功能来保持文件或目录分支的平行性.允许通过拷贝数据来创建分支,并记录与源文件
的关系.也能帮助你将一个分支的修改复制到另外其他的支流上.总的来说,能够映射出不同的工作拷贝.这样
就可以在不同的分支上进行工作.

使用分支
图:Figure 4.2. Starting repository layout
假设Sally与你同时拥有"calc"项目的工作副本,并都有/calc/trunk的工作副本.所有项目相关的文件都
在/calc目录下,因为你们的团队已经商定/calc/trunk用于存放开发主线.
此时你被要求完成一个任务就是新增项目的一个基本新特性.这将需要很长的时间来完成,并可能回影响到项
目中的大部分晚间.问题是你不想与Sally有任何冲突,她正在修改项目中的一些存在的小BUG.并依赖于最新发
布的项目版本,这里(/calc/trunk)主线版本是最有效的.如果你提交修改那么肯定会打乱Sally的修改工作.
一种策略就是进入一个空洞:你和Sally在一到两周内停止共享信息.那就是开始获取整顿在你工作副本的所有
文件,并不做任何提交一直到你完成工作任务.这个方案存在着很多问题,第一,这样一来做不安全.很多人喜欢
频繁的将工作结果上传到版本库,已防止工作副本被突发事件破坏引起的后果.第二,不够容易.如果你在不同
的机器上工作,你就需要手工的将工作副本进行拷贝修改.最后,当你完成你的所有修改后,你将发现很难将你
的工作合并到主线项目的代码中去.
更好的解决方法就是创,建所有你自己的分支.能频繁的提交工作在不与其他人的冲突下.也能有选择性的共享
信息.

创建一个分支
创建一个分支非常简单-只需要用svn copy命令拷贝项目就可以.Subversion不单支持单文件,也支持整个文件
目录的分支创建.在此例中,我们要拷贝/calc/trunk文件夹.那么应该把拷贝放在那里呢?任何地方你想要放置
的地方.这里需要提到项目的策略在库中有/calc/branches目录空间,并你想要拷贝的目录名重命名为my-
calc-branch.
有两种不同的方法来进行拷贝.首先介绍有些麻烦的方法.只是为了让概念清晰一点.首先,检出版本库./calc.
使用svn copy命令拷贝要进行分支的文件目录.
$ cd bigwc
$ svn copy trunk branches/my-calc-branch
$ svn status
A  +   branches/my-calc-branch
在这个例自立,拷贝命令递归拷贝trunk下的文件到新的工作目录.branches/my-calc-branch.你可以从svn
status 命令,心得目录被添加版本库中.同时注意"+"符号前面的字母A.他表明添加的列表是一些数据的拷贝,
并不是新添加的版本库的数据.当年提交修改后,版本库就会创建/calc/branches/my-calc-branch在版本库中
通过拷贝/calc/trunk,而不是通过工作副本将数据传送到版本库.
$ svn commit -m "Creating a private branch of /calc/trunk."
Adding         branches/my-calc-branch
Committed revision 341.
现在介绍一种简单的创建分支的方法,那就是可以通过给svn copy 命令传入两个URL路径来实现.
$ svn copy http://svn.example.com/repos/calc/trunk \
           http://svn.example.com/repos/calc/branches/my-calc-branch \
      -m "Creating a private branch of /calc/trunk."
Committed revision 341.
从版本库的角度来看,实际上这两种方法并无任何区别.注意区别只在与本地客户端,后者可以立即执行分支任
务,简单,并不需要你检出庞大的工作副本.这种方法是最常用的.
图 4.3. Repository with new copy

廉价的拷贝
Subversion的库经过特别的设计.当你拷贝一个文件目录是,你不需要担心会占用大量的版本库容量-实际上版
本库并不会真正的拷贝数据.取而代之的是建立一个新的目录路口来指向已存在的目录树.如果你是UNIX的用
户,这与磁盘连接的概念是相同的.后面对文件或是目录的修改也是影响被拷贝文件目录.任何能够使用该概念
的地方Subversion都会利用该理念.
这也是为什么听到廉价拷贝这个词.我们不需要担心文件目录有多大-拷贝的花费都是非常微小的.这种特性也
是每次提交所做的事,每个版本都是一次廉价拷贝.除了很少的一点修改数据进行保存.
当然,这些机制或数据共享对于用户都是隐藏不可见的.我们能简单的看到拷贝目录.主要点就是拷贝是非常廉
价的,无论是时间还是空间.如果你用这种方法拷贝是非常快的.当然可以随心所欲的进行分支.

使用分支进行工作
现在我们建立了项目的一个份支,我们就可以检出该分支并开始工作使用它.
$ svn checkout http://svn.example.com/repos/calc/branches/my-calc-branch
A  my-calc-branch/Makefile
A  my-calc-branch/integer.c
A  my-calc-branch/button.c
Checked out revision 341.
这个工作副本并无任何特别之处;只是简单镜像了一个库中项目.当你提交修改后,Sally并不期望当她更新工
作副本的时候看到这些修改.因为她的工作副本是/calc/trunk.
让我们假设看看一个星期里所发生的事
      You make a change to /calc/branches/my-calc-branch/button.c, which creates revision 342.
      You make a change to /calc/branches/my-calc-branch/integer.c, which creates revision 343.
      Sally makes a change to /calc/trunk/integer.c, which creates revision 344.
现在这里有两条独立的开发线
图Figure 4.4. The branching of one file's history

分支背后的关键概念
这里有两点重要的内容需要在这里记住.第一,Subversion并没有冲突分支的概念-它只知道怎么去进行拷贝.
当你拷贝一个目录是,结果就是目录是一个独立的分支.你可能回想像一个不同的目录被建立或被处理.但对于
Subversion只是平常的目录控制区别只是再扩展一个历史日志信息.第二,因为这种拷贝机制,Subversion的分
支只是平常的存储在版本库中,而不像其他的版本控制系统,分支是真正存储了目录文件.
注意,Subversion并不支持不同版本库之间拷贝也使用映射机制,所以他只能在同版本库下工作.