CVS 使用实例

来源:互联网 发布:java报表是什么 编辑:程序博客网 时间:2024/06/06 05:13

CVS 使用实例

2009-06-05
高宏伟
于哈尔滨市通达街291号

 CVS 相信大家已经很熟悉了。本文的目的是想通过一个实例让大家对CVS的用法有一个大致的了解。如果大家在使用过程中有什么问题,可以用QQ或E-Mail与我联系。我的QQ:21807822 E-Mail是dukejoe@163.com。那么我们就闲话少说直入正题吧。我这篇文章基于的环境如下,在阅读本文之前,建议读者至少要熟悉Linux的安装和基本的配置。

操作系统RedHat Enterprise Linux 4 (Update 4)安装过程注意

  1. 为了防止其它干扰,我关闭了防火墙,SELinux
  2. 安装telnet服务
  3. 安装vsftp
准备两台计算机

一台用于安装RedHat Enterprise Linux4
另一台用于安装Windows XP Home Edition

    首先可以从http://www.nongnu.org/cvs/ 这里下载cvs,或者直接点击这个链接下载cvs-1-11-22.zip (Windows版本二进制文件) cvs-1.11.23.tar.bz2(Linux x86 版本源代码)

安装cvs需要使用root权限。经典的从源代码安装如下:

[root@joerhel4 cvs-1.11.23]# ./configure
[root@joerhel4 cvs-1.11.23]# make
[root@joerhel4 cvs-1.11.23]# make install

make install之后,进入/etc/xinetd.d目录,新建一个cvsserver文件,文件内容如下:

service cvspserver
{
flags = REUSE
socket_type = stream
wait = no
user = root
server = /usr/bin/cvs
server_args = -f --allow-root=/home/cvs/cvsroot pserver
log_on_failure += USERID
disable = no
}

cvsserver文件保存后,重启xinetd。命令为

/etc/rc.d/init.d/xinetd restart

现在我们可以检查一下cvs server是否启动。命令为

[root@joerhel4 xinetd.d]# netstat -lnp|grep 2401
tcp 0 0 0.0.0.0:2401 0.0.0.0:* LISTEN 12394/xinetd
[root@joerhel4 xinetd.d]# netstat -l | grep cvs
tcp 0 0 *:cvspserver *:* LISTEN
[root@joerhel4 xinetd.d]#

至此CVS的Server端已经安装并成功启动了。下一步我们在Windows上安装一下客户端,CVS的客户端比较常用的是WinCVS和TortoiseCVS。他们都是图形方式的,又直观又方便。所以我也就不多介绍了。很多朋友一般是在使用CVS命令行时遇到问题了。所以下面我就着重介绍一下CVS命令行的使用。刚才高宏伟和大家说过,我们下载了cvs-1-11-22.zip。我们在C盘新建一个cvs目录,把cvs-1-11-22.zip中的cvs.exe解压到这个目录下。然后在“我的电脑”-->“属性”-->“高级”-->“环境变量”的PATH里,加入C:/CVS。然后关闭cmd,再重新打开一个cmd,这时输入cvs,屏幕应该有如下反应,就说明安装正常了。

C:/>cvs
Usage: cvs [cvs-options] command [command-options-and-arguments]
where cvs-options are -q, -n, etc.
(specify --help-options for a list of options)
where command is add, admin, etc.
(specify --help-commands for a list of commands
or --help-synonyms for a list of command synonyms)
where command-options-and-arguments depend on the specific command
(specify -H followed by a command name for command-specific help)
Specify --help to receive this message
The Concurrent Versions System (CVS) is a tool for version control.
For CVS updates and additional information, see
the CVS home page at http://www.cvshome.org/ or
the CVSNT home page at http://www.cvsnt.org/
C:/>

    在使用cvs之前,要使用init来RedHat Enterprise Linux 4上创建仓库。以本文为例,我们在/home/cvs目录下建立一个cvsroot目录做为仓库。使用命令cvs -d /home/cvs/cvsroot init 。命令执行后应该在/home/cvs/cvsroot目录下自动新建一个CVSROOT目录,这就说明仓库创建成功了。

    在Windows XP的客户端上,我们现在新建一个目录src,假定是我们项目中使用的源代码目录。在目录中我们建立makefile,test1.cpp 两个文件,假定是我们使用的源代码。以我的本机为例就是:D:/working/QA/prj_test1/src,读者如果是和本文一步一步操作下来的话,那最好目录也保持一致,以免产生错误。使用命令行之前,我们先设置一下环境变量CVSROOT,设置CVSROOT的好处就是不需要每次都输入这么一长串的字符。而如果你要想使用其它的CVSROOT时,还可以使用cvs的-d 选项来覆盖。使用cvs的第一件事就是登录login。现在让我们看一下如何登录到刚才我们设置好的仓库上。

D:/working/QA/prj_test1/src>set CVSROOT=:pserver:cvs@192.168.148.129/home/cvs/cvsroot
D:/working/QA/prj_test1/src>cvs login
Logging in to :pserver:cvs@192.168.148.129:2401/home/cvs/cvsroot
CVS password:
D:/working/QA/prj_test1/src>

其中pserver是指我们当前使用的协议,cvs是cvs的登录用户名,192.168.148.129是cvs server的IP地址,/home/cvs/cvsroot是我们刚才创建的仓库路径。

当我们开始做一个项目之前,首先要把他import到我们的cvs server中。cvs提供了几种可能。

  1. 从无到有,即然是一个新的项目,那可能在建立cvs之初,我们还没有什么像样的源代码需要import到仓库中。
  2. 很多实际的工作中,我们会发现,当我们开始import新项目时,我们总是已经有一部的源代码。这时我们可以直接把现有的代码import到仓库中。
  3. 从其它的系统中把项目导入到现在的工程中。这种可能就超出了本文的范围,如果读者有兴趣可以与我联系,我们再共同的深入探讨这个问题。QQ:21807822 e-mail:dukejoe@163.com

好,现在我们cd到D:/working/QA/prj_test1/src目录下,把我们的源代码import到仓库中,命令如下:

D:/working/QA/prj_test1/src>set CVSROOT=:pserver:cvs@192.168.148.129/home/cvs/cvsroot
D:/working/QA/prj_test1/src>cvs login
Logging in to :pserver:cvs@192.168.148.129:2401/home/cvs/cvsroot
CVS password:
D:/working/QA/prj_test1/src>cvs import -m "import source by gaohw" src gaohw_vendor gaohw_release
N src/makefile
N src/test1.cpp
No conflicts created by this import
D:/working/QA/prj_test1/src>

-m 是日志消息
src 是仓库(repository) 下的一个目录名。它也可以是一个路径。我们用这个名称来标识不同的源代码集合。
gaohw_vendor 是整个分支的标签。
gaohw_release 是用来识别每次import的,这个要求名称之前从来没有使用过。

import就相当于单位又来了一个新项目。立项之后我们就可以开始软件开发工作了。平时开发时我们最常使用的是update和commit两个命令。比如项目组工作一天后,在下班时会使用commit把当天的工作成果提交到cvs上,第二天早上,测试组会从 cvs上把头一天的源代码使用update命令更新到本地,开始测试。这就是一个比较简单而且很理想的工作流程(当然实际开发中要比这个复杂得多)。

D:/working/QA/prj_test1/src_checkout/src>cvs commit -m "修改1 by 高宏伟"
cvs commit: Examining .
Checking in test1.cpp;
/home/cvs/cvsroot/src/test1.cpp,v <-- test1.cpp
new revision: 1.2; previous revision: 1.1
done D:/working/QA/prj_test1/src_checkout/src>

注意:我开了两个cmd就好像项目组有两个人A和B,先都checkout,然后其中A修改test1.cpp,并commit。在B的目录中执行update,效果如下,我们可以看到B目录中的test1.cpp被更新到最新状态和A的文件是相同的了,这样项目组成员就可以协调步调,保持一致。

D:/working/QA/prj_test1/src_checkout/src>cvs update -P -d -C
cvs update: Updating .
P test1.cpp D:/working/QA/prj_test1/src_checkout/src>

现在我们已经import了一些源代码,也有多个人checkout,并在上面做了一些工作,经过不同的人update和commit几次之后,我们可能想看一下,现在源代码的各种情况。那我们应该使用什么命令呢?在这里我们可以使用cvs log 命令来查看文件的日志信息

D:/working/QA/prj_test1/src>cvs log test1.cpp
RCS file: /home/cvs/cvsroot/src/test1.cpp,v
Working file: test1.cpp
head: 1.3
branch:
locks: strict
access list:
symbolic names:
gaohw_release: 1.1.1.1
gaohw_vendor: 1.1.1
keyword substitution: kv
total revisions: 4; selected revisions: 4
description:
----------------------------
revision 1.3
date: 2009/06/04 07:06:30; author: cvs; state: Exp; lines: +1 -0
修改2
----------------------------
revision 1.2
date: 2009/06/04 07:00:18; author: cvs; state: Exp; lines: +0 -5
修改1 by 高宏伟
----------------------------
revision 1.1
date: 2009/06/04 06:29:33; author: cvs; state: Exp;
branches: 1.1.1;
Initial revision
----------------------------
revision 1.1.1.1
date: 2009/06/04 06:29:33; author: cvs; state: Exp; lines: +0 -0
import source by gaohw
============================================================================= D:/working/QA/prj_test1/src>

通过log命令的输出,我们就可以看到现在test1.cpp文件的所有日志信息。

在CVS中,版本号的问题也是大家普通比较关心的。我们通过上面log的日志输出,可以看到有类似1.1.1,这样的版本号。所以我们很自然的想到,在我们开发过程中,如果版本号要从1.x变成2.0时,我们是不是也要让CVS里的这个版本号和项目中的版本号进行统一。CVS的官方是这样给我们建议的,CVS中的版本号只做为CVS内部使用,项目中如果要使用版本号,比如发布2.0或其它里程碑,应该尽量使用tag命令,而不是非要强求CVS里显示的版本号统一。官方的这个建议,我个人认为最好还是遵循,毕竟不要自找麻烦嘛,是吧?好了,那我们看一下如何使用tag命令

D:/working/QA/prj_test1>set CVSROOT=:pserver:cvs@192.168.148.129/home/cvs/cvsroot
D:/working/QA/prj_test1>cvs login
Logging in to :pserver:cvs@192.168.148.129:2401/home/cvs/cvsroot
CVS password: D:/working/QA/prj_test1>cvs tag gaohw_release_1_0 src
cvs tag: Tagging src
T src/makefile
T src/test1.cpp D:/working/QA/prj_test1>cvs log
cvs log: Logging src RCS file: /home/cvs/cvsroot/src/makefile,v
Working file: src/makefile
head: 1.1
branch: 1.1.1
locks: strict
access list:
symbolic names:
gaohw_release_1_0: 1.1.1.1
gaohw_release: 1.1.1.1
gaohw_vendor: 1.1.1
keyword substitution: kv
total revisions: 2; selected revisions: 2
description:
----------------------------
revision 1.1
date: 2009/06/04 06:29:33; author: cvs; state: Exp;
branches: 1.1.1;
Initial revision
----------------------------
revision 1.1.1.1
date: 2009/06/04 06:29:33; author: cvs; state: Exp; lines: +0 -0
import source by gaohw
============================================================================= RCS file: /home/cvs/cvsroot/src/test1.cpp,v
Working file: src/test1.cpp
head: 1.3
branch:
locks: strict
access list:
symbolic names:
gaohw_release_1_0: 1.3
gaohw_release: 1.1.1.1
gaohw_vendor: 1.1.1
keyword substitution: kv
total revisions: 4; selected revisions: 4
description:
----------------------------
revision 1.3
date: 2009/06/04 07:06:30; author: cvs; state: Exp; lines: +1 -0
修改2
----------------------------
revision 1.2
date: 2009/06/04 07:00:18; author: cvs; state: Exp; lines: +0 -5
修改1 by 高宏伟
----------------------------
revision 1.1
date: 2009/06/04 06:29:33; author: cvs; state: Exp;
branches: 1.1.1;
Initial revision
----------------------------
revision 1.1.1.1
date: 2009/06/04 06:29:33; author: cvs; state: Exp; lines: +0 -0
import source by gaohw
============================================================================= D:/working/QA/prj_test1/src>cvs status -v test1.cpp
===================================================================
File: test1.cpp Status: Up-to-date Working revision: 1.3
Repository revision: 1.3 /home/cvs/cvsroot/src/test1.cpp,v
Sticky Tag: (none)
Sticky Date: (none)
Sticky Options: (none) Existing Tags:
gaohw_1_0_patches (branch: 1.3.2)
gaohw_release_1_1 (revision: 1.3)
gaohw_release_1_0 (revision: 1.3)
gaohw_release (revision: 1.1.1.1)
gaohw_vendor (branch: 1.1.1) D:/working/QA/prj_test1/src>

当我们要发布产品的1.0时,我们就创建一个名为gaohw_release_1_0的tag,这样。项目组的其它成员再需要使用release 1.0 时,就可以直接checkout gaohw_release_1_0 这个标签,就可以把1.0正式版导出。以此类推,我们要建立里程碑1.5时,就可以再创建一个gaohw_release_1_5,需要使用哪个版本,就以tag名为标准导出。而使用log命令,我们可以在symbolic names这个项目中看到目前已经创建的tag,也就是我们当前使用的各个里程碑。

D:/working/QA/prj_test1>cvs tag -d abc123 src
cvs tag: Untagging src
D src/makefile
D src/test1.cpp D:/working/QA/prj_test1>

使用cvs tag的 -d 我们可以删除一个错误的tag。有人可能要问了,那如果我不是要删除,只要要重命名一下,那我应该怎么做。其实重命令tag在CVS中,就是创建一个新的tag,然后再删除一个旧的tag。请看下面的实例:

D:/working/QA/prj_test1>cvs tag gaohw_release_1_0_joe src
cvs tag: Tagging src
T src/makefile
T src/test1.cpp D:/working/QA/prj_test1>cvs rtag -r gaohw_release_1_0_joe gaohw_release_1_1 src
cvs rtag: Tagging src D:/working/QA/prj_test1>cvs rtag -d gaohw_release_1_0_joe src
cvs rtag: Untagging src D:/working/QA/prj_test1>  

这其中我们使用了rtag,rtag和tag的区别是tag要使用本地的工作目录中的副本,而rtag是使用远端仓库中的工作目录。比如最开始我们新建tag时,可能使用的是本地最新的副本,所以我使用了tag,但是后来我是要修改一个tag名,那我根本没必要把这个tag下的所有文件都下载到本地,再new,delelet,我只要对仓库中的tag直接new,delete就可以了。

下面我们要说的一个CVS功能是,创建分支(Branch)。有时我们会遇到这样的情况。项目组正在为4.0做着紧张的开发,突然用户反馈说,3.0版本有问题,而且已经反映到老总那里,老总要求立刻为用户解,项目组先是在现有的代码中找到了BUG,并加以修正,可以现在的4.0还没有稳定,不能发布给用户,这时最好的办法是先checkout出3.0,然后在这个基础上创建分支Branch,3.1,以3.1版本为基础修改BUG,然后以3.0的分支为一个版本发布给用户,解决用户的燃眉之急,倒过手来,我们再在发布4.0时同步修改掉这个BUG。这样即不会搞乱我们现有的4.0的开发任务,又会让用户比较满意。

D:/working/QA/prj_test1> cvs rtag -b -r gaohw_release_3_0 gaohw_release_3_0_patches src
cvs rtag: Tagging src
D:/working/QA/prj_test1/patches>cvs checkout -r gaohw_release_3_0_patches src
cvs checkout: Updating src
U src/makefile
U src/test1.cpp D:/working/QA/prj_test1/patches>

至此,我们基本上完成了CVS的大部分常用功能。CVS更多的东西,我们可以参考http://www.nongnu.org/cvs/ 同时,再好的工具也有不能完全的事情,技术是在发展的,但从一个时间点上来看,技术总是有一定的局限性,很多事情除了使用CVS,更多的应该是配合一种管理的理念和工作的经验,才可以使工作更加的高效。非常感谢大家能用这么您宝贵的时间来阅读本文。如果还有什么问题,请大家与我联系QQ:21807822,e-mail: dukejoe@163.com 转载请注明出处为http://blog.donews.com/dukejoe/archive/2009/06/05/1509086.aspx,并保留作者姓名和本句话,谢谢合作

原创粉丝点击