技术开发 频道

CVS版本管理

【IT168 技术文章】

    我参与的项目release好一段时间了,这期间经历了市场血与火的洗礼。做应用软件的就是这样,你一定会碰到不同用户的不同需求,你需要为其定制开发。好,当有A省的用户有特殊的需求的时候,我们就用CVS为其建立一个新的project。同理,当有B省用户有特殊的需求的时候,我们还是采用同样的办法。我们一开始没有觉得这样哪里不好,为不同的用户建立不同的project,很清晰,维护起来还挺方便。就像《后天》里的情节哪样,你总是要对你不正确的做法付出惨痛的代价。我们很快发现了我们的做法的致命伤,当我们需要修改一个bug,或者是升级程序,加入通用的功能的时候,我们需要手工同步很多版本。god,大量的重复劳动!我清楚的听到我邻座那个可爱的女孩的抱怨:真麻烦,要同步这么多版本。

    有的时候,我觉得自己很幸运。当有一个问题困扰着我的时候,我准备上一个常去的论坛向guru请教的时候,发现大家正在那里热火朝天的讨论着这个问题。这次也差不多,一天晚上和一个以前的同事聊了一些关于版本管理的问题。那个同事现在在一家外企工作,据称他们的版本管理很规范,有很专业的专门人员来做这件事情。他告诉我,应该可以采用CVS的分支功能来解决这个问题。虽然我当时云里雾里,不太明白,他也不是做版本管理的,但是,重要的是这个idea。我是一个听人劝的人,马上从一个同事那里揩来《CVS-开源软件开发技术》那本书。仔细的研究了一下分支的功能。啧啧,这就是我想要的,哈哈,在屋里跳了一会小天鹅。嗯,程序员总是这样大喜大悲的!

    把我的轻骑兵音箱调到很大声,听着《痴心绝对》。我喜欢这样写文章。好吧,让我们看看什么是CVS的分支。

    我们把一个项目的一个主要开发过程称作开发主线。当某一个特殊事件发生的时候,例如,有一个用户有特殊的需求,于是就从这个开发主线里分离出来一个叉,以满足用户特殊的需求,那么这个叉有它自己的发展方向,这就是分支,就像是一个大树在春暖花开的时候,长出来的新枝。

           ---------分支
          /
         /
        /
  ------●----------------------------开发主线

    上面这个点,代表开发主线的最新版本,那么这个时候可以从开发主线建立分支来进行定制开发。接下来,开发主线和分支就可以有各种的发展方向。而且,如果可以的话,分支的代码可以重新合并到开发主线中。开发主线的代码也可以更新到分支代码中。

    假设在我们的home目录下的proj目录就是我们的工程。下面具体看一下,如何建立分支:

    1、先在开发主线上创建一个标签,就是上图中那个点。这样做是为了以后可能有使主干重新回到分支创建时的状态的需求。在你的工程目录的top level下执行cvs tag Root-of-Version_2.5.0.0。

    2、创建分支:cvs tag -b ln_version_branch(-b选项就是创建分支)。

    3、接下来,你可以在工程目录的top level下直接执行cvs update -r ln_version_branch转到分支上进行工作。也可以通过cvs co -r ln_version_branch -d ln_proj proj命令新checkout一份分支的本地拷贝。-d选项是创建本地目录名字。这里建议用第二种用法,因为在一个本地拷贝下通过命令来回在主线和分支转换,容易产生混淆,你也可能忘记这么去做。

    4、这样分支的开发和主线的开发就可以分离开。如果需要的话,可以把分支上的代码合并到开发主线上,当然在合并的过程中可能需要解决一些冲突。cvs update -j ln_version_branch,通过这样的命令把分支代码合并到主线上。当然我们这里的例子是针对用户特殊需求产生的分支,一般不会把分支合并到开发主线中。但是,对于bug修改等产生的分支,就会有需求把分支合并到主线上。这里有一点要强调的是,当开发主线的程序员合并分支的代码的时候,需要互相沟通。在开发主线程序员成功合并分支代码后,在主线代码上要设立一个点(cvs tag)来标志这次合并;在分支代码上开发的程序员,在合并之后,也要建立一个点来标志这次合并,例如,cvs tag ln_version_1。这样做的好处是当下次在进行代码合并的时候,在开发主线上的程序员可以通过命令cvs update -j ln_version_1 -j ln_version_branch,这里ln_version_branch代表分支的末梢,因此该命令不是重新合并整个分支代码,而是合并自从合并点ln_version_1到现在修改的代码,这样可以防止重新合并整个分支而带来的冲突。

    5、对于我们这里针对用户特殊需求产生的分支,可能更多需要的是把开发主线上的代码更新到分支上。cvs update -j HEAD,这里HEAD代表了主干的末梢,也就是这个命令合并了主线在创建该分支伊始到目前为止,所有的主线上修改的代码。这里还是需要分支开发人员和主线开发人员沟通。在分支上也需要设立一个点来标志这次合并,这样如果主线需要合并分支代码的时候,可以根据这个点进行新的合并,而不是合并整个分支。主线开发人员也需要设置点来标志这次合并,例如,cvs tage merged-ln_version_1 ,这样下次分支在合并主线代码的时候可以cvs update -j merged-ln_version_1 -j HEAD ,这样防止了分支重复合并主线上的代码,而只是合并最新的修改。

    上面我们可以看到,一个主要规则是,当进行代码合并的时候,一定要注意沟通,合理的设置合并点。并且,合并点的名字也应该望文生义^_^。各个线上的合并工作也最好由一个人来做。如果合并点设置不当,那么分支带来的好处可能就会打折扣。并且如果管理的不好,整个项目可能会很乱,产生意大利面条式的分支^_^。

    CVS的工作模式:
    CVS的基本工作模式如下:

    CVS服务器(代码文档库) /     |       \    (版 本 同 步)   /      |        \    开发者1  开发者2   开发者3
    CVS在服务器端维护代码文档库,不同的开发者在本地机器上建立对应代码树,并利用CVS保持本地代码文档同代码文档库的一致。当由于多个开发者对文件的同时修改造成本地与库中的代码文件冲突时,CVS报告并协助解决冲突代码的合并问题。普通开发者(非管理员)对CVS的使用流程如下所示:

    Check out(获取) -------------------- Merge(合并) | | ^ v v Conflict(冲突) | Modify(修改)-> Update(更新) ---------------- ^ | | | No Conflict(无冲突) | v Update(更新) <- Commit(提交) | v Export(导出)

    check out命令只需在开始建立本地代码树时使用一次,其后更新本地代码则使用update命令。update命令比较服务器和本地代码库的区别,并把本地代码树中过时的文件自动更新。当完成对代码的修改之后,在提交代码之前同样需要使用update命令,以获取他人并行修改的的代码。如果出现冲突(即对同一文件同时进行了修改),CVS将在本地代码中把两者都保留并标记出来,要求开发者处理冲突。在冲突不存在或已解决的情况下,使用commit命令将服务器代码更新为本地代码。CVS要求为更改提供注释,并自动为更新的文件处理版本编号。当软件需要正式发布时,使用export命令导出不包含CVS设置信息的源代码树。

    CVS的管理员还使用包括init, import, admin等命令对服务器和代码库进行配置和设置。

0
相关文章