cvs tag与branch区别总结

总结了一下网上的资源:

branch“分支”指不同需求或功能差异很大的同一系统的不同产品线,每一个新的产品线都可以演化成新的产品,branch一般在产生新的产品线的时候创建。
tag“标记”经过QA人员测试之后的,确认达到要求时才创建的类似历史记录的标记,tag是记录版本历史的里程碑,tag是不可修改的。

我们checkout时指定版本的branch,可以取出该分支的最新的代码,进行修改之后,可以commit回cvs中去。
我们checkout时指定版本的tag,可以取出创建该标记时刻的代码,从该tag中取出的代码是反映历史的、不可修改的。

一个系统可以包含多个tag和branch,tag只能属于某个branch,一个branch可以包含多个tag。

默认的branch是Main,分支Main最新代码的tag是默认的Head标签。新的branch可以创建新的自定义名称,新的tag可以创建新的自定义名称。


在实现上,branch和tag,对于svn都是使用copy实现的,所以他们在默认的权限上和一般的目录没有区别。至于何时用tag,何时用branch,完全由人主观的根据规范和需要来选择,而不是强制的(比如cvs)。

一般情况下,
tag,是用来做一个milestone的,不管是不是release,都是一个可用的版本。这里,应该是只读的。更多的是一个显示用的,给人一个可读(readable)的标记。
branch,是用来做并行开发的,这里的并行是指和trunk进行比较。

      
    CVS (Concurrent Version Control System) 是一个能让很多程式开发者同时做软体开发的非常强大工具。对于它可能大部分软件工程师都应该有所接触,起码也是对这个名字如雷贯耳了。CVS的基本命令和使用,网上已经有了很多的教程,我就不再罗嗦。本文想介绍的,可以说是CVS的精华,同时又是对初学者来说很难理解和掌握的(包括当时我也花了很多精力去学习)的两个功能:tag和branch。
 
一、 tag
  1.指示你正工作在那个branch上。(因为每个branch都有一个tag.
 2.如果你不想更新一个大目录树的一部分,你可以利用sticky tag.
    1.1 revision number(修订号)
       要理解tag,首先要介绍一下revision number(修订号)。在CVS中每个文件的版本都有一唯一的 revision number。修订号的形式一般是这样的:`1.1',`1.2',`1.3.2.2' 甚至是 `1.3.2.2.4.5'。一个修订号总有偶数个用句号分隔的十进制数。按照默认,文件第一个修订号是 1.1。每个新的修订号的最右边的数会比它的上一个修订号的最右边的数大 1。下图显示了一些修订号,较新的版本在右边。
 
            +-----+    +-----+    +-----+    +-----+    +-----+
            ! 1.1 ! ----! 1.2 !----! 1.3 !----! 1.4  !----! 1.5 !
            +-----+    +-----+    +-----+    +-----+    +-----+
     其实,对于大多数 cvs 用户来说,不需要考虑修订号;他们只要知道 cvs 已经自动地加上了类似 1.1,1.2 之类的修订号就可以了。
 
       1.2 tag (标签)
    由于每个文件都有自己的修订号,每次提交该文件一次,它的修订号就会就会增加。这样就会产生一个问题:对于软件的某一个发行版,源文件的修订号可能都不一样。例如:
     ci.c            5.21
     co.c            5.9
     ident.c         5.3
     rcs.c           5.12
     rcsbase.h       5.11
     rcsdiff.c       5.10
     rcsedit.c       5.11
     rcsfcmp.c       5.9
     rcsgen.c        5.10
     rcslex.c        5.11
     rcsmap.c        5.2
     rcsutil.c       5.10
    因此,要checkout某一个特定的发行版的所有源码的时候,如果是要根据修订号来的话,是异常繁琐和难以跟踪的。这个时候,就要用到CVS提供的很炫的一个功能了:tag(标签)。
      
       标签可以用来标记多个文件的一组修订号,你可以想象标签以文件名为横轴,以版本号为纵轴绘制了一个曲线图(或者也可以想象成在一个由文件名和版本号组成的矩阵里面绘制的曲线)。    

 

 
    在过去的某个时候带 * 的版本号已被标记上标签。你可以把标签想象成一条经过所有被标记的文件的曲线。当你抓住线就得到所有标签标记的版本了。也可以通过另一种方式来看待这一点:把被同一个标签标记的所有版本号经过的曲线拉直, 然后直直地看过去。

 

 
    1.3 tag命令的用法                                                              
       下面的例子说明了怎样给一个文件添加标签。命令必须在模块的工作目录中发出。也就是说,你应该在 backend.c 文件所在的目录中发出该命令。
 
     $ cvs tag rel-0-4 backend.c
     T backend.c
     $ cvs status -v backend.c
     ===================================================================
     File: backend.c         Status: Up-to-date
    
         Version:            1.4     Tue Dec 1 14:39:01 1992
         RCS Version:        1.4     /u/cvsroot/yoyodyne/tc/backend.c,v
         Sticky Tag:         (none)
         Sticky Date:        (none)
         Sticky Options:     (none)
    
         Existing Tags:
             rel-0-4                     (revision: 1.4)
    
    很少对单个孤立文件添加标签。一种更常见的用法是在产品开发周期中的各个里程碑任务完成后对一个模块的所有文件添加标签,比如在发行版完成的时候。
 
     $ cvs tag rel-1-0 .
     cvs tag: Tagging .
    T Makefile
     T backend.c
     T driver.c
     T frontend.c
     T parser.c
 
    (当把一个目录作为 cvs 的一个参数的时候,该命令不仅对该目录下的所有文件执行操作,而且也会递归地对该目录下的所有子目录中的文件执行操作。)    
 
       如果要检出一个模块的某个版本,可以使用checkout -r命令。在 checkout 命令中使用 `-r' 标志可以检出一个模块某个版本。下面的命令可以很容易地取出模块 `tc' 1.0 发行版的所有源文件:
 
     $ cvs checkout -r rel-1-0 tc
 
        1.4 什么时候使用tag
        tag的功能就像是给你的工程的某个时刻建立了一个快照。添加了tag后,不论你最源文件做了任何修改,只要发现你的修改发生了错误,或者是如果有人宣称在某个版本里有个 bug,但你在当前工作的副本中是找不到那个 bug,都可以根据tag重新rollback回去,或checkout出那个快照。
        tag给开发人员带了这样的便利,因此在任何重要的开发阶段,都应该打上tag。
 
        一般性的,在下面的情况都应该考虑给你的工程简历一份快照(tag):
        完成了某个重要的功能
        在每一个milestone
        在去掉某个存在功能之前
        在测试开始之前
        在你对源文件做重大修改之前
        新建分支(branch,下文会详细谈到)的时候
        很并分支之前
 
       当然了,这些都是一般性的建议。其实我感觉是只要你觉得做的修改可能会有副作用的时候,就应该打上tag。


二. Branches

命令为cvs tag 加上-b选项

cvs 允许你把修改隔离在各自的开发线上,这就是分支(branch)。当你改变一个分支中的文件时,这些更改不会出现在开发主干(main trunk)和其它分支中。

在这之后你可以使用 merge 把这些变更从一个分支移动到另一个分支(或主干)。合并首先使用 cvs update -j 命令,将这些变更合并到工作目录。然后你可以提交这个版本,这样也可以将这些变更作用于其它的分支。

下面的操作描述约定都以目录为操作对象。

1. 建立一个分支

使用 tag -b 去建立一个分支;例如,假定你现在有一个工作副本:

 $ cvs tag -b NLP23_BRANCH

这将基于工作副本的当前版本分离出一个分支,并分配 NLP23_BRANCH 名字给该分支。

有一点对理解分支很重要,分支是在 CVS 仓库中创建,而非在工作副本中创建。正如上面的例子,基于当前版本创建一个分支不会自动把当前的工作副本切换到新的分支上。

$ cvs tag -b -r  rs_1-0-0-0_PD_BL_MAIN  NLP23_BRANCH

这个命令的结果是建立了一个命名为 ` NLP23_BRANCH ' 的新版本分支,它是基于标记为 `rs_1-0-0-0_PD_BL_MAIN' 的基线版本。

2. 检出与更新分支

你可以通过两种方式恢复分支:重新从仓库检出一份或是从现有的工作副本切换过去。

为了从仓库检出一个分支,使用 checkout 命令并带上 -r 标志,后面是这个分支的标签(branchtag)名:

 $ cvs checkout -r NLP23_BRANCH ps/se/rs/


或者如果你已有了一个工作副本,你可以使用 update -r 命令切转到这个分支: 

  $ cvs update -r NLP23_BRANCH ps/se/rs/


或者使用另一个等效的命令: 

 $ cd ps/se/rs/
  $ cvs update -r NLP23_BRANCH

这对工作副本为主干代码或是其它分支都是有效的 – 上面的命令将把它切换到指名的分支。同 update 命令相类似,update -r 合并你所做的任何改变,通知你出现的冲突。

一旦你的工作副本已经转向一个特定的分支,它将一直保持在这个分支内,除非你又做了其它的操作。这意味着从这个工作副本提交的变更将加到这个分支的新版本中,而不影响到主干版本和其它分支。

想看一个工作副本是基于哪一个分支,可以使用 status 命令。在它们输出中查找一个 Sticky tag 的域(参阅 Sticky tags) – 那就是 cvs 告诉你当前工作文件分支号的方式:

     $ cvs status -v rs.h
     ===================================================================
     File: rs.h          Status: Up-to-date

     Version:            1.7     Sat Dec  5 18:25:54 1992
     RCS Version:        1.7    /u/cvsroot/yoyodyne/ps/se/rs/rs.h,v
         Sticky Tag:         NLP23_BRANCH (branch: 1.7.2)
         Sticky Date:        (none)
         Sticky Options:     (none)

         Existing Tags:
             NLP23_BRANCH             (branch: 1.7.2)
             rs_1-0-0-0_PD_BL         (revision: 1.7)

3. 合并一整个分支

你可以把另一个分支上的修改合并到你的工作副本,只要在 update 子命令中加 -j tagname 的标志。

-j 的意思是“join”。

Consider this revision tree:

    +-----+    +-----+    +-----+    +-----+
     ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !      <- The main trunk
     +-----+    +-----+    +-----+    +-----+
                     !
                     !
                     !   +---------+    +---------+
  Branch NLP23_BRANCH -> +---! 1.2.2.1 !----! 1.2.2.2 !
                         +---------+    +---------+
                                              !
                                        rs_1-6-0-0_PD_BL


分支NLP23_BRANCH 的最后版本的tag是rs_1-6-0-0_PD_BL。下面的例子假定模块 ps/se/rs/ 只包含一个文件 rs.h。 

$ cvs checkout ps/se/rs/        # Retrieve the latest revision, 1.4

$ cvs update -j NLP23_BRANCH     # Merge all changes made on the branch,
                          # i.e. the changes between revision 1.2
                          # and 1.2.2.2, into your working copy
                          # of the file.

$ cvs commit -m "Included NLP23_BRANCH" # Create revision 1.5.

请注意,此操作是把分支上得变化,也就是分支得起点(revision 1.2)版本和分支得终点(revision 1.2.2.2)版本的差异,合并到你的工作副本中,不是将分支得终点(revision 1.2.2.2)版本的所有内容合并到你的工作副本中。

在合并时可能会发生冲突。如果这种情况发生,你应该在提交新版本之前解决它。

cvs合并命令只是工具支持,但不能保证合并后的程序逻辑上的正确性,合并后必须人工从逻辑上确认合并结果。

合并命令执行完后,强烈建议使用 cvs diff 命令检查合并结果和合入版本(及-j tag中tag指示的版本)的差别,以确保物理合并的完整性。

4. 在文件添加和删除的情况下?

如果你在合并时做的改变涉及到添加或删除一些文件,update -j 将反映这些变化。

例如:

     cvs update -A
     touch a b c
     cvs add a b c ; cvs ci -m "added" a b c
     cvs tag -b branchtag
     cvs update -r branchtag
     touch d ; cvs add d
     rm a ; cvs rm a
     cvs ci -m "added d, removed a"
     cvs update -A
     cvs update -jbranchtag

在执行这些命令且 cvs commit一完成之后,文件 a 将被删除,而文件 d 将被加入到主分支。

注意使用 update -j tagname 也许行但结果可能不是你想要的。

注意,当用静态标签(-j tagname)而不是动态标签(-j branchname)从一个分支合并改变时,cvs 一般不会删除文件,因为 cvs 不会自动给 dead 版本添加静态标签。除非静态标签是手工添加到 dead 版本上的。使用分支标签从分支合并所有改变或使用两个静态标签作为合并端点合并都会在合并中将企图的修改传播开。



    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值