SVN trunk、branch、tag的用法

Subversion有一个很标准的目录结构,是这样的。
好比项目是proj,svn地址为svn://proj/,那么标准的svn布局是

svn://proj/|+-trunk+-branches+-tags
这是一个标准的布局,trunk为主开发目录,branches为分支开发目录,tags为tag存档目录(不容许修改)。可是具体这几个目录应该如何使用,svn并无明确的规范,更多的仍是用户本身的习惯。

对于这几个开发目录,通常的使用方法有两种。我更多的是从软件产品的角度出发(好比freebsd),由于互联网的开发模式是彻底不同的。
第一种方法,使用trunk做为主要的开发目录。
通常的,咱们的全部的开发都是基于trunk进行开发,当一个版本/release开发告一段落(开发、测试、文档、制做安装程序、打包等)结束后,代码处于冻结状态(人为规定,能够经过hook来进行管理)。此时应该基于当前冻结的代码库,打tag。当下一个版本/阶段的开发任务开始,继续在trunk进行开发。
此时,若是发现了上一个已发行版本(Released Version)有一些bug,或者一些很急迫的功能要求,而正在开发的版本(Developing Version)没法知足时间要求,这时候就须要在上一个版本上进行修改了。应该基于发行版对应的tag,作相应的分支(branch)进行开发。
例如,刚刚发布1.0,正在开发2.0,此时要在1.0的基础上进行bug修正。
按照时间的顺序

1.0开发完毕,代码冻结
基于已经冻结的trunk,为release1.0打tag
此时的目录结构为
svn://proj/
             +trunk/ (freeze)
             +branches/
             +tags/
                     +tag_release_1.0 (copy from trunk)
2.0开始开发,trunk此时为2.0的开发版
发现1.0有bug,须要修改,基于1.0的tag作branch
此时的目录结构为
svn://proj/
             +trunk/ ( dev 2.0 )
             +branches/
                           +dev_1.0_bugfix (copy from tag/release_1.0)
             +tags/
                     +release_1.0 (copy from trunk)
在1.0 bugfix branch进行1.0 bugfix开发,在trunk进行2.0开发
在1.0 bugfix 完成以后,基于dev_1.0_bugfix的branch作release等
根据须要选择性的把dev_1.0_bugfix这个分支merge回trunk(何时进行这步操做,要根据具体状况)
这是一种很标准的开发模式,不少的公司都是采用这种模式进行开发的。trunk永远是开发的主要目录。

第二种方法,在每个release的branch中进行各自的开发,trunk只作发布使用。
这种开发模式当中,trunk是不承担具体开发任务的,一个版本/阶段的开发任务在开始的时候,根据已经release的版本作新的开发分支,而且基于这个分支进行开发。仍是举上面的例子,这里面的时序关系是。

1.0开发,作dev1.0的branch
此时的目录结构
svn://proj/
             +trunk/ (不担负开发任务 )
             +branches/
                           +dev_1.0 (copy from trunk)
             +tags/
1.0开发完成,merge dev1.0到trunk
此时的目录结构
svn://proj/
             +trunk/ (merge from branch dev_1.0)
             +branches/
                           +dev_1.0 (开发任务结束,freeze)
             +tags/
根据trunk作1.0的tag
此时的目录结构
svn://proj/
             +trunk/ (merge from branch dev_1.0)
             +branches/
                           +dev_1.0 (开发任务结束,freeze)
             +tags/
                     +tag_release_1.0 (copy from trunk)
1.0开发,作dev2.0分支
此时的目录结构
svn://proj/
             +trunk/
             +branches/
                           +dev_1.0 (开发任务结束,freeze)
                           +dev_2.0 (进行2.0开发)
             +tags/
                     +tag_release_1.0 (copy from trunk)
1.0有bug,直接在dev1.0的分支上修复svn

==============================================================布局

主干(trunk)、分支(branch )、标记(tag)测试

在SVN中Branch/tag在一个功能选项中,在使用中也每每产生混淆。编码

 
在实现上,branch和tag,对于svn都是使用copy实现的,因此他们在默认的权限上和通常的目录没有区别。至于什么时候用tag,什么时候用branch,彻底由人主观的根据规范和须要来选择,而不是强制的(好比cvs)。

通常状况下,spa

trunk:是用来作主方向开发的,一个新模块的开发,这个时候就放在trunk,当模块开发完成后,须要修改,就用branch。
branch:是用来作并行开发的,这里的并行是指和trunk进行比较。
tag:是用来作一个milestone的,无论是否是发布版本,但都是一个可用的版本。这里,应该是只读的。更多的是一个显示用的,给人一个可读的标记。

好比,3.0开发完成,这个时候要作一个tag,tag_release_3_0,而后基于这个tag作发布,好比安装程序等。trunk进入 3.1的开发,可是3.0发现了bug,那么就须要基于tag_release_3_0作一个分支(branch),branch_bugfix_3_0,基于这个branch进行bug修改,等到bugfix结束,作一个tag,tag_release_3_0_1,而后,根据须要决定 branch_bugfix_3_0是否并入主干(trunk)。

对于svn还要注意的一点,就是它是全局版本号,其实这个就是一个tag的标记,因此咱们常常能够看到,什么什么release,基于xxx项目的 2xxxx版本。就是这个意思了。可是,它还明确的给出一个tag的概念,就是由于这个更加的可读,毕竟记住tag_release_1_0要比记住一个很大的版本号容易的多。

branches:分枝
当多我的合做,可能有这样的状况出现:John忽然有个想法,跟原先的设计不太一致,多是功能的添加或者日志格式的改进等等,总而言之,这个想法可能须要花一段时间来完成,而这个过程当中,John的一些操做可能会影响Sally的工做,John从现有的状态单独出一个project的话,又不能及时获得 Sally对已有代码作的修正,并且独立出来的话,John的尝试成功时,跟原来的合并也存在困难。这时最好的实践方法是使用branches。 John创建一个本身的branch,而后在里面实验,必要的时候从Sally的trunk里取得更新,或者将本身的阶段成果聚集到trunk中。
建立分支的命令:设计

(svn copy SourceURL/trunk DestinationURL/branchName -m "Creating a private branch of xxxx/trunk." )

trunk:主干
主干,通常来讲就是开发的主要呆的地方,


tag::标记
在通过了一段时间的开发后,项目到达了一个里程碑阶段,你可能想记录这一阶段的代码的状态,那么你就须要给代码打上标签。
建立标记的命令:
(svn cp file:///svnroot/mojavescripts/trunk file:///svnroot/mojavescripts/tags/mirrorutils_rel_0_0_1-m "taged mirrorutils_rel_0_0_1")

另有一说,无所谓谁对谁错。

trunk:表示开发时版本存放的目录,即在开发阶段的代码都提交到该目录上。

branches:表示发布的版本存放的目录,即项目上线时发布的稳定版本存放在该目录中。

tags:表示标签存放的目录。

在这须要说明下分三个目录的缘由,若是项目分为一期、二期、三期等,那么一期上线时的稳定版本就应该在一期完成时将代码copy到branches上,这样二期开发的代码就对一期的代码没有影响,如新增的模块就不会部署到生产环境上。而branches上的稳定的版本就是发布到生产环境上的代码,若是用户使用的过程当中发现有bug,则只要在branches上修改该bug,修改完bug后再编译branches上最新的代码发布到生产环境便可。版本控制

 

 

tags的做用是将在branches上修改的bug的代码合并到trunk上时建立个版本标识,之后branches上修改的bug代码再合并到trunk上时就从tags的version到branches最新的version合并到trunk,以保证前期修改的bug代码不会再合并。

-------------------------------------------------------------------------------------------

一直以来用svn只是看成cvs,也历来没有仔细看过文档,直到今天用到,才去翻看svn book文档,惭愧

需求一:
有一个客户想对产品作定制,可是咱们并不想修改原有的svn中trunk的代码。
方法:
用svn创建一个新的branches,从这个branche作为一个新的起点来开发
svn copy svn://server/trunk svn://server/branches/ep -m "init ep"

Tip:

若是你的svn中之前没有branches这个的目录,只有trunk这个,你能够用
svn mkdir branches
新建个目录

需求二:
产品开发已经基本完成,而且经过很严格的测%日志

 

================================================================视频

——简单的对比server

  SVN的工做机制在某种程度上就像一颗正在生长的树:

  • 一颗有树干和许多分支的树
  • 分支从树干生长出来,而且细的分支从相对较粗的树干中长出
  • 一棵树能够只有树干没有分支(可是这种状况不会持续好久,随着树的成长,确定会有分支啦,^^)
  • 一颗没有树干可是有不少分支的树看起来更像是地板上的一捆树枝
  • 若是树干患病了,最终分支也会受到影响,而后整棵树就会死亡
  • 若是分支患病了,你能够剪掉它,而后其余分支还会生长出来的哦!
  • 若是分支生长太快了,对于树干它可能会很是沉重,最后整棵树会垮塌掉
  • 当你感受你的树、树干或者是分支看起来很漂亮的时候,你能够给它照张相,这样就就能够记得它在那时是多么的赞。

——Trunk

  Trunk是放置稳定代码的主要环境,就好像一个汽车工厂,负责将成品的汽车零件组装在一块儿。

  如下内容将告诉你如何使用SVN trunk:

  • 除非你必须处理一些容易且能迅速解决的BUG,或者你必须添加一些无关逻辑的文件(好比媒体文件:图像,视频,CSS等等),不然永远不要在trunk直接作开发
  • 不要由于特殊的需求而去对先前的版本作太大的改变,如何相关的状况都意味着须要创建一个branch(以下所述)
  • 不要提交一些可能破坏trunk的内容,例如从branch合并
  • 若是你在某些时候偶然间破坏了trunk,bring some cake the next day (”with great responsibilities come… huge cakes”)

——Branches

  一个branch就是从一个SVN仓库中的子树所做的一份普通拷贝。一般状况它的工做相似与UNIX系统上的符号连接,可是你一旦在一个SVN branch里修改了一些文件,而且这些被修改的文件从拷贝过来的源文件独立发展,就不能这么认为了。当一个branch完成了,而且认为它足够稳定的时候,它必须合并回它原来的拷贝的地方,也就是说:若是原来是从trunk中拷贝的,就应该回到trunk去,或者合并回它原来拷贝的父级branch。

  如下内容将告诉你如何使用SVN branches:

  • 若是你须要修改你的应用程序,或者为它开发一个新的特性,请从trunk中建立一个新的branch,而后基于这个新的分支进行开发
  • 除非是由于必须从一个branch中建立一个新的子branch,不然新的branch必须从trunk建立
  • 当你建立了一个新branch,你应当当即切换过去。若是你没有这么作,那你为何要在最初的地方建立这个分支呢?

——Tags

  从表面上看,SVN branches和SVN tags没有什么差异,可是从概念上来讲,它们有许多差异。其实一个SVN tags就是上文所述的“为这棵树照张相”:一个trunk或者一个branch修订版的命名快照。

  如下内容将告诉你如何使用SVN tags:

  • 做为一个开发者,永远不要切换至、取出,或者向一个SVN tag提交任何内容:一个tag比如某种“照片”,并非实实在在的东西,tags只可读,不可写。
  • 在特殊或者须要特别注意的环境中,如:生产环境(production)、?(staging)、测试环境(testing)等等,只能从一个修复过的(fixed)tag中checkout和update,永远不要commit至一个tag。
  • 对于上述说起到的环境,能够建立以下的tags:“production”,“staging”,“testing”等等。你也能够根据软件版本、项目的成熟程度来命名tag:“1.0.3”,“stable”,“latest”等等。
  • 当trunk已经稳定,而且能够对外发布,也要相应地从新建立tags,而后再更新相关的环境(production, staging, etc)

——工做流样例

  假设你必须添加了一个特性至一个项目,且这个项目是受版本控制的,你差很少须要完成以下几个步骤:

  1. 使用SVN checkout或者SVN switch从这个项目的trunk得到一个新的工做拷贝(branch)
  2. 使用SVN切换至新的branch
  3. 完成新特性的开发(固然,要作足够的测试,包括在开始编码前)
  4. 一旦这个特性完成而且稳定(已提交),并通过你的同事们确认,切换至trunk
  5. 合并你的分支至你的工做拷贝(trunk),而且解决一系列的冲突
  6. 从新检查合并后的代码
  7. 若是可能的话,麻烦你的同事对你所编写、更改的代码进行一次复查(review)
  8. 提交合并后的工做拷贝至trunk
  9. 若是某些部署须要特殊的环境(生成环境等等),请更新相关的tag至你刚刚提交到trunk的修订版本
  10. 使用SVN update部署至相关环境
Thing to Name Name Style Examples1 Examples2
Release branch RB-rel RB-1.0 RB-1.0.1a
Releases REL-rel REL-1.0 REL-1.0.1a
Bug fix branches BUG-track BUG-3035 BUG-10871
Pre-bug fix PRE-track PRE-3035 PRE-10871
Post-bug fix POST-track POST-3035 POST-10871