分类: 嵌入式
2010-06-21 17:00:09
说明:
笔者对于CVS的使用仅仅限于个人的(即没有团队)、本机的、浅层的使用。下面的例子中仅仅是为了说明问题,在实际应用中所用到的不外那么几个命令:import、checkout、update等等。
(1)、安装
安装过程似乎不用说也可以吧?我所用的Red Flag系统已经安装好了,但FC10上没有安装,可以这样:
# yum install xinetd
按提示进行安装就可以了。
(2)、添加用户
任何一个开发团队使用CVS都应当添加CVS组以及几个CVS用户。但本文没有使用这种方式,因为在一个人使用的情况下,添加组、用户略显麻烦,这告诉我们遇到具体的情况要具体分析并制定符合实际的方案。
如果实在想这样做,添加组和用户也十分easy,如下:
# groupadd cvs // cvs组
# useradd cvs_latelee // cvs用户
# usermod –g cvs cvs_latelee // 添加cvs_latelee到cvs组中
# passwd cvs_latelee // 修改密码
(3)、创建CVS仓库目录
目录名称可以为cvs_root或cvs_home或者其它有意义的名称。可以在自己的家目录创建,也可以在系统的/目录下创建,如果是个人使用,可以以root权限将这些目录的权限修改为自己的,如果是团队使用,可以将仓库目录的属性修改为0774。
因为在/目录中,普通用户是不能创建目录的,所以必须以root身份来创建:
# cd /
# mkdir cvs_home
# chown –R latelee:latelee cvs_home
对于latelee:latelee,前一个是指用户,后一个是指用户组,也可以指定为cvs组。当然,在自己的家目录下就不存在这种问题了。
(4)、服务器配置
CVS配置文件在/etc/xinetd.d/cvs文件中(不保证所有的Linux系统中都是此路径),以root身份来修改:
# default: off
# description: The CVS service can record the history of your source \
# files. CVS stores all the versions of a file in a single \
# file in a clever way that only stores the differences \
# between versions.
service cvspserver
{
disable = no
port = 2401
socket_type = stream
protocol = tcp
wait = no
user = latelee // 用户
passenv = PATH
server = /usr/bin/cvs
env = HOME=/var/cvs
server_args = -f --allow-root=/cvs_home pserver // 目录
# bind = 127.0.0.1
}
user指定了用户,server_args指定了仓库目录(/cvs_home)以及访问方式(pserver)。
(5)、启动服务
命令如下:
#service xinetd restart
可以看一下2401端口是否处于监听状态:
# netstat -ln | grep 2401
tcp 0 0 0.0.0.0:2401 0.0.0.0:* LISTEN
在fedora中可以让xinetd开机自动启动。
(6)、初始化服务器
初始化服务器有两种方式,一是在终端export CVSROOT环境变量,二是使用在系统中初始化环境变量,前者只在一个终端有效,后者比较方便。在自己家目录的.bashrc文件最后添加:
CVSROOT=/cvs_home
export CVSROOT
注意:这里的“家目录”是指你所用的用户目录,比如有人喜欢使用root,那么就要在/root/.bashrc文件添加了。
CVS的初始化命令,普通用户与root用户都可执行,但最好是使用你所用的用户来执行该命令:
$ cvs init
初始化成功,会在/cvs_home目录生成一个CVSROOT目录。里面有许多文件,是与CVS相关的。不用理会也行。
注意:如果设置了CVSROOT环境变量,则输入cvs命令时可以不指定仓库目录。此处设置了在.bashrc中环境变量CVSROOT=/cvs_home
(1)、常用
检入(import),这里没有-m选项,所以会出现默认的编辑器VI,可以在里面写一些有关的信息。
[latelee@localhost thread]$ cvs import thread thread_project ver_0-1
N thread/thread.cpp
N thread/thread.h
N thread/main.cpp
N thread/Makefile
No conflicts created by this import
没有check out,不能update:
[latelee@localhost thread]$ cvs update
cvs update: in directory .:
cvs [update aborted]: there is no version here; run 'cvs checkout' first
check out时,会在当前目录下创建该工程目录,注意:我们本来的目录是/home/latelee/linux-c/thread/,之后则变为:/home/latelee/linux-c/thread/thread,当然,也可以在别的目录下check out
[latelee@localhost thread]$ cvs co thread
cvs checkout: Updating thread
U thread/Makefile
U thread/main.cpp
U thread/thread.cpp
U thread/thread.h
可以看一下某些文件的状态:
[latelee@localhost thread]$ cvs status -v main.cpp
=========================================================
File: main.cpp Status: Locally Modified
Working revision: 1.1.1.1 Thu Apr 22 04:43:21 2010
Repository revision: 1.1.1.1 /cvs_home/thread/main.cpp,v
Sticky Tag: (none)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
ver_0-1 (revision: 1.1.1.1)
thread_project (branch: 1.1.1)
修改某些文件了,但还没有提交到仓库,更新会出现:
[latelee@localhost thread]$ cvs update
cvs update: Updating .
M main.cpp
M thread.cpp
M thread.h
? thread
其中M代表当前目录下已修改了的文件,这里有三个,?是说thread在仓库里没有找到,因为我检入库时是没有这个文件的,这里是编译后生成的可执行文件,一般来说,在仓库里的基本上都是源代码和说明文档等等,在这里,我不将编译生成的结果检入库。好,那么就检入库:
[latelee@localhost thread]$ cvs commit
cvs commit: Examining .
Checking in main.cpp;
/cvs_home/thread/main.cpp,v <-- main.cpp
new revision: 1.2; previous revision: 1.1
done
Checking in thread.cpp;
/cvs_home/thread/thread.cpp,v <-- thread.cpp
new revision: 1.2; previous revision: 1.1
done
Checking in thread.h;
/cvs_home/thread/thread.h,v <-- thread.h
new revision: 1.2; previous revision: 1.1
done
当输入cvs commit时,我没有带参数(这里的参数是指文件),则代表目录下所有的文件都入库,这里有三个。回车后,将会出现文本编辑器(此处是VI,当然也可以修改,如-e emacs),在VI中记录修改日志。保存退出,即可。
下面再check out这个工程,在上一目录中执行cvs co thread,它不再是check out,而是update,因为当前目录已有了thread目录了。
[latelee@localhost thread]$ ls
main.cpp Makefile thread thread.cpp thread.h //注意,第三个文件thread其实是我们的工程目录
[latelee@localhost thread]$ cvs co thread
cvs checkout: Updating thread
我们再看一下main.cpp的状态:
[latelee@localhost thread]$ cvs status -v main.cpp
=========================================================
File: main.cpp Status: Up-to-date
Working revision: 1.2 Thu Apr 22 04:57:48 2010
Repository revision: 1.2 /cvs_home/thread/main.cpp,v
Sticky Tag: (none)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
ver_0-1 (revision: 1.1.1.1)
thread_project (branch: 1.1.1)
可以看到,版本已经变化了。
(2)、标记
我们创建一个标记:
[latelee@localhost thread]$ cvs tag pre_alpha_0-1
cvs tag: Tagging .
T Makefile
T main.cpp
T thread.cpp
T thread.h
标记名为pre_alpha_0-1,这个名称可以随意修改。
我也不知道下面这个是什么意思。在书上的:
[latelee@localhost thread]$ cvs update -d -r pre_alpha_0-1
cvs update: Updating .
U Makefile
U main.cpp
U thread.cpp
U thread.h
再看一下main.cpp的状态:
[latelee@localhost thread]$ cvs status -v main.cpp
=========================================================
File: main.cpp Status: Up-to-date
Working revision: 1.2 Thu Apr 22 05:02:20 2010
Repository revision: 1.2 /cvs_home/thread/main.cpp,v
Sticky Tag: pre_alpha_0-1 (revision: 1.2)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
pre_alpha_0-1 (revision: 1.2)
ver_0-1 (revision: 1.1.1.1)
thread_project (branch: 1.1.1)
改名:
[latelee@localhost thread]$ cvs tag -r pre_alpha_0-1 pre_alpha_0-1_branch_root
cvs tag: Tagging .
T Makefile
T main.cpp
T thread.cpp
T thread.h
[latelee@localhost thread]$ cvs status -v main.cpp
=========================================================
File: main.cpp Status: Up-to-date
Working revision: 1.2 Thu Apr 22 05:02:20 2010
Repository revision: 1.2 /cvs_home/thread/main.cpp,v
Sticky Tag: pre_alpha_0-1 (revision: 1.2)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
pre_alpha_0-1_branch_root (revision: 1.2)
pre_alpha_0-1 (revision: 1.2)
ver_0-1 (revision: 1.1.1.1)
thread_project (branch: 1.1.1)
可见,版本1.2有两个标记,下面我们删除一个:
[latelee@localhost thread]$ cvs tag -d pre_alpha_0-1
cvs tag: Untagging .
D Makefile
D main.cpp
D thread.cpp
D thread.h
[latelee@localhost thread]$ cvs status -v main.cpp
cvs status: main.cpp is no longer in the repository
=========================================================
File: main.cpp Status: Entry Invalid
Working revision: 1.2 Thu Apr 22 05:02:20 2010
Repository revision: No revision control file
Sticky Tag: pre_alpha_0-1 - MISSING from RCS file!
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
pre_alpha_0-1_branch_root (revision: 1.2)
ver_0-1 (revision: 1.1.1.1)
thread_project (branch: 1.1.1)
是不是有点麻烦?更名过程就是将旧标记贴上新的标记,再将旧标记删除。
(3)、分支测试:
在上面的基础上,添加一个分支:
[latelee@localhost thread]$ cvs rtag -r pre_alpha_0-1_branch_root -b pre_alpha_0-1_branch thread
cvs rtag: Tagging thread
[latelee@localhost thread]$ cvs status -v main.cpp
cvs status: main.cpp is no longer in the repository
=========================================================
File: main.cpp Status: Entry Invalid
Working revision: 1.2 Thu Apr 22 05:02:20 2010
Repository revision: No revision control file
Sticky Tag: pre_alpha_0-1 - MISSING from RCS file!
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
pre_alpha_0-1_branch (branch: 1.2.2)
pre_alpha_0-1_branch_root (revision: 1.2)
ver_0-1 (revision: 1.1.1.1)
thread_project
回到上一目录,将一个分支check out出来:
[latelee@localhost thread]$ cvs co -r pre_alpha_0-1_branch thread
cvs checkout: Updating thread
看一下main.cpp的状态:
[latelee@localhost thread]$ cvs status main.cpp
=========================================================
File: main.cpp Status: Up-to-date
Working revision: 1.2 Thu Apr 22 05:34:38 2010
Repository revision: 1.2 /cvs_home/thread/main.cpp,v
Sticky Tag: pre_alpha_0-1_branch (branch: 1.2.2)
Sticky Date: (none)
Sticky Options: (none)
注意:在实际开发中,分支最好不要跟主干的目录混在一起。
(4)、远程访问(检出代码)
下面这种方法只适合一个终端,因为export只在一个终端有效。
[latelee@FightNow latelee]$ export CVSROOT=:pserver:latelee@192.168.1.13/cvsroot
[latelee@FightNow latelee]$ cvs login
Logging in to :pserver:latelee@192.168.1.13:2401/cvsroot
CVS password: (在这里输入密码)
没有错误,说明已经连接上服务器了。这里进入到一个测试目录:
[latelee@FightNow latelee]$ cd work/nfs
[latelee@FightNow nfs]$ ls
hello-arm
将代码checkout出来
[latelee@FightNow nfs]$ cvs co camera-server
cvs checkout: Updating camera-server
U camera-server/Makefile
U camera-server/log.txt
U camera-server/main.c
cvs checkout: Updating camera-server/rtp
U camera-server/rtp/Config.h
U camera-server/rtp/Hdr_Builder.c
U camera-server/rtp/Macros.h
U camera-server/rtp/Makefile
U camera-server/rtp/Network.c
U camera-server/rtp/Network.h
U camera-server/rtp/Proto.h
U camera-server/rtp/RTP.c
U camera-server/rtp/RTP.h
U camera-server/rtp/Types.h
U camera-server/rtp/Utils.c
U camera-server/rtp/coucou.txt
U camera-server/rtp/cscope.out
U camera-server/rtp/rtp_rcv.c
U camera-server/rtp/rtp_rcv.h
U camera-server/rtp/rtp_rcv_print.c
U camera-server/rtp/sysqueue.h
cvs checkout: Updating camera-server/video
U camera-server/video/color.c
U camera-server/video/color.h
U camera-server/video/debug-msg.h
U camera-server/video/huffman.h
U camera-server/video/my-types.h
U camera-server/video/utils.c
U camera-server/video/utils.h
U camera-server/video/v4l2uvc.h
[latelee@FightNow nfs]$ cvs co camera-client
cvs checkout: Updating camera-client
U camera-client/Makefile
U camera-client/arm-Makefile
U camera-client/cscope.out
U camera-client/log.txt
U camera-client/main.c
U camera-client/my-types.h
U camera-client/my_udp.c
cvs checkout: Updating camera-client/rtp
U camera-client/rtp/Config.h
U camera-client/rtp/Hdr_Builder.c
U camera-client/rtp/Macros.h
U camera-client/rtp/Network.c
U camera-client/rtp/Network.h
U camera-client/rtp/Proto.h
U camera-client/rtp/RTP.c
U camera-client/rtp/RTP.h
U camera-client/rtp/Types.h
U camera-client/rtp/Utils.c
U camera-client/rtp/cscope.out
U camera-client/rtp/debug-msg.h
U camera-client/rtp/my-types.h
U camera-client/rtp/rtp_send.c
U camera-client/rtp/rtp_send.h
U camera-client/rtp/sysqueue.h
cvs checkout: Updating camera-client/v4l2
U camera-client/v4l2/debug-msg.h
U camera-client/v4l2/my-types.h
U camera-client/v4l2/v4l2uvc.c
U camera-client/v4l2/v4l2uvc.h
目录中多了两个文件夹。
[latelee@FightNow nfs]$ ls
camera-client camera-server hello-arm
[latelee@FightNow nfs]$
上述例子中没有讲如何在开发过程中添加或删除文件(或目录),下面讲一下。在thread工程中添加了fork.cpp文件。
[latelee@51 thread]$ cvs add fork.cpp
cvs add: scheduling file `fork.cpp' for addition
cvs add: use 'cvs commit' to add this file permanently
[latelee@51 thread]$ cvs commit
cvs commit: Examining .
cvs commit: Up-to-date check failed for `main.cpp'
cvs commit: Up-to-date check failed for `thread.cpp'
cvs commit: Up-to-date check failed for `thread.h'
cvs [commit aborted]: correct above errors first!
出错了!因为没有check out,正确的cvs commit显示如下:
[latelee@51 thread]$ cvs commit
cvs commit: Examining .
RCS file: /cvs_home/thread/fork.cpp,v
done
Checking in fork.cpp;
/cvs_home/thread/fork.cpp,v <-- fork.cpp
initial revision: 1.1
done
删除一个文件(fork.cpp)过程如下:
[latelee@51 thread]$ rm fork.cpp
[latelee@51 thread]$ cvs remove fork.cpp
cvs remove: scheduling `fork.cpp' for removal
cvs remove: use 'cvs commit' to remove this file permanently
[latelee@51 thread]$ cvs commit
cvs commit: Examining .
Removing fork.cpp;
/cvs_home/thread/fork.cpp,v <-- fork.cpp
new revision: delete; previous revision: 1.1
done
至于目录的添加删除,就不显示了。
又:本文的例子不是同一时间、同一台PC上完成的,但对于使用CVS来说,是没有关系的。