﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-CONAN ZONE-文章分类-CVS</title><link>http://www.blogjava.net/conans/category/32367.html</link><description>你越挣扎我就越兴奋</description><language>zh-cn</language><lastBuildDate>Thu, 26 Jun 2008 16:50:26 GMT</lastBuildDate><pubDate>Thu, 26 Jun 2008 16:50:26 GMT</pubDate><ttl>60</ttl><item><title>CVS服务器快速指南</title><link>http://www.blogjava.net/conans/articles/210984.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Thu, 26 Jun 2008 15:39:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/210984.html</guid><description><![CDATA[简介
<p>　　CVS 是 Concurrent Version System(并行版本系统)的缩写，用于版本管理.如果大家曾经参与过多人协作开发的项目，大家肯定有这样的痛苦经历：由于多个人同时修改同一个文件， 自己辛辛苦苦修改的程序被别人彻底删除了.另外，如果你的软件/程序已经发布了三个版本， 而这时候用户需要你修改第二个版本的东西，也许你会因为只保留了最新版本而痛哭流涕。还有就是你对程序做了一些修改，但是修改很少，你只想给远方的同事发一个两个版本之间的差别文件，这样可以免于邮箱不够大，网速太慢之类的问题.为了解决类似这样的问题，以及诸如生成补丁文件，历史版本修改等，一帮黑客(褒义)在原先 Unix 体系里很成熟的 SCCS 和 RCS 的基础上，开发了 CVS。(SCCS：Source Code Control System，RCS：Revision Control System)。</p>
<p>　　CVS 的基本工作思路是这样的：在一台服务器上建立一个仓库，仓库里可以存放许多不同项目的源程序。由仓库管理员统一管理这些源程序.这样，就好象只有一个人在修改文件一样.避免了冲突.每个用户在使用仓库之前，首先要把仓库里的项目文件下载到本地。用户做的任何修改首先都是在本地进行，然后用 cvs 命令进行提交，由 cvs 仓库管理员统一 修改.这样就可以做到跟踪文件变化，冲突控制等等.</p>
<p>　　由于 CVS 是典型的 C/S 结构的软件，因此它也分成服务器端和客户端两部分。不过大多数CVS 软件都把它们合二为一了。我们这里就分别从服务器和客户端的角度讨论cvs的使用。</p>
<p>　　Cvs服务器安装</p>
<p>　　首先确保系统安装有cvs：</p>
<p>　　[root@mail xinetd.d]# rpm -qa|grep cvs </p>
<p>　　cvs-1.11.1p1-3 </p>
<p>　　如果命令输出类似于上面的输出则说明系统已经安装有cvs，否则就需要从安装光盘中安装cvs的rpm包。 </p>
<p>　　一 创建CVS属主用户：</p>
<p>　　# useradd -d /cvsroot cvs </p>
<p>　　# chmod 771 /cv sroot </p>
<p>　　二、建立CVS仓库(初始化cvs)</p>
<p>　　# su cvs </p>
<p>　　$ cvs -d /cvsroot init </p>
<p>　　$exit </p>
<p>　　# </p>
<p>　　四、启动cvs服务器</p>
<p>　　在/etc/xinetd.d/目录下创建文件cvspserver，内容如下：</p>
<p>　　# default: on </p>
<p>　　# description: The cvs server sessions; </p>
<p>　　service cvspserver </p>
<p>　　{ </p>
<p>　　socket_type = stream </p>
<p>　　wait = no </p>
<p>　　user = root </p>
<p>　　server = /usr/bin/cvs </p>
<p>　　server_args = -f --allow-root=/cvsroot pserver </p>
<p>　　log_on_failure += USERID </p>
<p>　　only_from = 192.168.0.0/24 </p>
<p>　　} </p>
<p>　　其中only_from是用来限制访问的，可以根据实际情况不要或者修改。</p>
<p>　　修改该文件权限：</p>
<p>　　# chmod 644 cvspserver </p>
<p>　　然后重新启动xinetd：</p>
<p>　　# /etc/rc.d/init.d/xined restart </p>
<p>　　然后察看cvs服务器是否已经运行：</p>
<p>　　[root@mail xinetd.d]# netstat -lnp|grep 2401 </p>
<p>　　tcp 0 0 0.0.0.0:2401 0.0.0.0:* LISTEN 7866/xinetd</p>
<p>　　则说明cvs服务器已经运行。</p>
<p>　　五、创建用来访问cvs的用户</p>
<p>　　前面创建的cvs用户是cvs仓库管理用户，而为了让用户访问则还需要一个访问用户：</p>
<p>　　# useradd cvspub </p>
<p>　　# usemod &#8211;G cvs cvspub </p>
<p>　　这里添加了一个用户cvspub，并且将该用户添加到cvs组中。</p>
<p>　　六、管理cvs服务器</p>
<p>　　管理 cvs 服务器.服务器可以用了，现在大家最关心的就是如何管理服务器，比如，我想让一些人有读和/或写 CVS 仓库的权限，但是不想给它系统权限怎么办呢？不难，cvs初始化结束以后，在管理员用户(这里是cvs用户)的主目录里有一个 CVSROOT 目录，这个目录里有三个配置文件：passwd, readers, writers。我们可以通过设置这三个文件来配置 CVS 服务器，下面分别介绍这几个文件的作用：</p>
<p>　　passwd：cvs 用户的用户列表文件，它的格式很象 shadow 文件：</p>
<p>　　{cvs 用户名}:[加密的口令]:[等效系统用户名]</p>
<p>　　如果你希望一个用户只是 cvs 用户，而不是系统用户，那么你就要设置这个文件，刚刚安装完之后这个文件可能不存在，你需要以cvs管理员身份(su cvs)用户手工创建，当然要按照上面格式；</p>
<p>　　第二个字段是该用户的加密口令，就是用 crypt (3) 加密的，你可以自己写一个程序来做加密，也可以用两个偷懒的方法：先创建一个系统用户，名字和 cvs 用户一样，口令就是准备给它的 cvs 用户口令，创建完之后从 /etc/shadow 把该用户第二个字段拷贝过来，然后 再把这个用户删除.这个方法对付数量少的用户比较方便，人一多就不合适了，而且还有冲突条件(race condition)的安全隐患，还要 root 权限，实在不怎么样，不过权益之计而已；另外一个方法就是利用apche的htpasswd命令创建passwd用户，添加用户只需要htpasswd passwd username即可添加用户到passwd文件中，不过需要在文件中对应行的最后添加一个&#8220;:&#8221;冒号和对应的等效系统用户名；最好的就是自己编写一个程序了来生成这个passwd文件了。</p>
<p>　　第三个字段就是等效系统用户名，实际上就是赋与一个 cvs 用户一个等效的系统用户的权限，看下面的例子你就明白它的功能了。</p>
<p>　　readers：有 cvs 读权限的用户列表文件，就是一个一维列表。在这个文件中的用户对 cvs</p>
<p>　　只有读权限。</p>
<p>　　writers：有 cvs 写权限的用户的列表文件，和 readers 一样，是一个一维列表。在这个文件中的用户对 cvs 有写权限。</p>
<p>　　上面三个文件在缺省安装的时候可能都不存在，需要我们自己创建，好吧，现在还是让我们用一个例子来教学吧.假设我们有下面几个用户需要使用 cvs：</p>
<p>　　cvsuser1, cvsuser2, henry, betty, anonymous</p>
<p>　　其中 laser 和 gumpwu 是系统用户，而henry, betty, anonymous 我们都不想给系统用户权限，并且 betty 和 anonymous 都是只读用户，而且 anonymous 更是连口令都没有。</p>
<p>　　然后编辑 cvs 管理员家目录里 CVSROOT/passwd 文件，加入下面几行：</p>
<p>　　laser:$xxefajfka;faffa33:cvspub</p>
<p>　　gumpwu:$ajfaal;323r0ofeeanv:cvspub</p>
<p>　　henry:$fajkdpaieje:cvspub</p>
<p>　　betty:fjkal;ffjieinfn/:cvspub</p>
<p>　　anonymous::cvspub</p>
<p>　　注意：上面的第二个字段(分隔符为 :)是密文口令，你要用程序或者用我的土办法生成。</p>
<p>　　编辑 readers 文件，加入下面几行：</p>
<p>　　anonymous</p>
<p>　　betty</p>
<p>　　编辑 writer 文件，加入下面几行：</p>
<p>　　laser</p>
<p>　　gumpwu</p>
<p>　　henry</p>
<p>　　这样就 ok 了，你再用几个用户分别登陆测试，就会发现一切都 ok 了。这里面的原理和说明我想就不多说了，其实很简单，和系统管理用户的概念是一样的。</p>
<p>　　七、建立新的CVS项目</p>
<p>　　一般我们都已经有一个或多个项目了，这样我们可以用下面步骤生成一个新的CVS项目。</p>
<p>　　将一个工程文件置于CVs中进行版本控制，在CVS 术语中称作导入(import)。从名字上就可以看出，在导入前需要为此作些准备工作。</p>
<p>　　输入操作的基本要求是有个&#8220;干净&#8221;的目录结构。&#8220;干净&#8221;的意思是不需要版本控制的文件都被移走了(如编译生成的文件，备份文件等等)。如果工程已经开始一段时间了，这就显得很重要。在目录中也许有些是不打算将其置于版本控制下的文件，但是又想将他们放在这里，这种情况下，你要在输入之前将它们移走，然后再移回来。</p>
<p>　　注意的是CVS 认为空目录是不存在的。如果想增加一个既不包含文件又不包含子目录的目录，需要在其下创建一个哑文件。建议你创建一个名为 README.txt 的文件，其内容为对目录的简要说明。</p>
<p>　　进入到已有项目的目录，比如叫 cvstest：</p>
<p>　　$cd cvstest </p>
<p>　　运行命令将项目文件导入到cvs仓库中：</p>
<p>　　$cvs import -m "this is a cvstest project" cvstest v_0_0_1 start </p>
<p>　　说明：import 是cvs的命令之一，表示向cvs仓库输入项目文件.</p>
<p>　　-m参数后面的字串是描述文本，对项目进行描述，如果不加 -m 参数，那么cvs会自动运行一个编辑器(一般是vi，但是可以通过修改环境变量EDITOR来改成你喜欢用的编辑器)让你输入信息，cvstest 是项目名称(实际上是仓库名，在CVS服务器上会存储在以这个名字命名的仓库里)</p>
<p>　　v_0_0_1是这个分支的总标记.没啥用(或曰不常用)</p>
<p>　　start 是每次 import 标识文件的输入层次的标记，没啥用。</p>
<p>　　这样我们就建立了一个CVS仓库了，然后，我们可以把这个测试项目的文件删除，试验如何从仓库获取文件这会在后面的客户端文章进行说明。</p>
<p>　　该文章借鉴了何伟平先生的很多内容，在此表示感谢！ </p>
<!-- 正文end -->
<img src ="http://www.blogjava.net/conans/aggbug/210984.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-26 23:39 <a href="http://www.blogjava.net/conans/articles/210984.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CVS使用手册</title><link>http://www.blogjava.net/conans/articles/210985.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Thu, 26 Jun 2008 15:39:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/210985.html</guid><description><![CDATA[<div class="entry-content">
<div class="entry-body">
<p>CVS是一个C/S系统，多个开发人员通过一个中心版本控制系统来记录文件版本，从而达到保证文件同步的目的。工作模式如下： </p>
<pre>       CVS服务器（文件版本库）<br />
/     |       \<br />
（版 本 同 步）<br />
/       |         \<br />
开发者1  开发者2   开发者3<br />
</pre>
<p>作为一般开发人员挑选2,6看就可以了，CVS的管理员则更需要懂的更多一些，最后还简单介绍了一些Windows下的cvs客户端使用，CVS远 程用户认证的选择及与BUG跟踪系统等开发环境的集成问题。</p>
<ol>
    <li><a href="http://www.chedong.com/tech/cvs_card.html#init">CVS环境初始化</a>：CVS环境的搭建 管理员
    <li><a href="http://www.chedong.com/tech/cvs_card.html#daily">CVS的日常使用</a>：日常开发中最常用的CVS命令， 开发人员 管理员
    <li><a href="http://www.chedong.com/tech/cvs_card.html#branch">CVS的分支开发</a>：项目按照不同进度和目标并发进行 管理员
    <li><a href="http://www.chedong.com/tech/cvs_card.html#ssh">CVS的用户认证</a>：通过SSH的远程用户认证，安全，简单 管理员
    <li><a href="http://www.chedong.com/tech/cvs_card.html#cvsweb">CVSWEB</a>：CVS的WEB访问界面大大提高代码版本比较的效率 管理员
    <li><a href="http://www.chedong.com/tech/cvs_card.html#tag">CVS TAG</a>：将$<span style="font-weight: bold">Id</span>$ 加入代码注释中，方便开发过程的跟踪开发人员
    <li><a href="http://www.chedong.com/tech/cvs_card.html#vss">CVS vs VSS</a>: CVS和Virsual SourceSafe的比较 开发人员 管理员
    <li><a href="http://www.chedong.com/tech/cvs_card.html#wincvs">WinCVS:</a> 通过SSH认证的WinCVS认证设置
    <li><a href="http://www.chedong.com/tech/cvs_card.html#cvstrac">基于CVSTrac的小组开发环境搭建</a>：通过CVSTrac实现web界面的CVS用户管理,集成的BUG跟踪和WIKI交流
    <li><a href="http://www.chedong.com/tech/cvs_card.html#auth">CVS中的用户权限管理</a>：基于系统用户的CVS权限管理和基于CVSROOT/passwd的虚拟用户管理 </li>
</ol>
<p>一个系统20%的功能往往能够满足80%的需求，CVS也不例外，以下是CVS最常用的功能，可能还不到它全部命令选项的20%，作为一般开发人员平时会用cvs update和cvs commit就够了，更多的需求在实际应用过程中自然会出现，不时回头看看相关文档经常有意外的收获。</p>
</div>
<div class="entry-more" id="more">
<h2><a name="init"></a>CVS环境初始化</h2>
环境设置：指定CVS库的路径CVSROOT
<p>tcsh<br />
setenv CVSROOT /path/to/cvsroot<br />
bash<br />
CVSROOT=/path/to/cvsroot ; export CVSROOT</p>
<p>后面还提到远程CVS服务器的设置：<br />
CVSROOT=:ext:$USER@test.server.address#port:/path/to/cvsroot CVS_RSH=ssh; export CVSROOT CVS_RSH<br />
<br />
初始化：CVS版本库的初始化。<br />
cvs init</p>
<p>一个项目的首次导入<br />
cvs import -m "write some comments here" project_name vendor_tag release_tag<br />
执行后：会将所有源文件及目录导入到/path/to/cvsroot/project_name目录下<br />
<em>vender_tag: 开发商标记<br />
release_tag: 版本发布标记</em></p>
<p>项目导出：将代码从CVS库里导出<br />
cvs checkout project_name<br />
<em>cvs 将创建project_name目录，并将最新版本的源代码导出到相应目录中。这个checkout和Virvual SourceSafe中的check out不是一个概念，相对于Virvual SourceSafe的check out是cvs update， check in是cvs commit。</em><br />
<br />
</p>
<h2><a name="daily"></a>CVS的日常使用<strong> </strong></h2>
<p>&nbsp;</p>
<p><strong>注意：第一次导出以后，就不是通过cvs checkout来同步文件了，而是要进入刚才cvs checkout project_name导出的project_name目录下进行具体文件的版本同步（添加，修改，删除）操作。</strong></p>
<p><u>将文件同步到最新的版本<br />
</u>cvs update<br />
<em>不制定文件名，cvs将同步所有子目录下的文件，也可以制定某个文件名/目录进行同步<br />
</em>cvs update file_name<br />
<em>最好每天开始工作前或将自己的工作导入到CVS库里前都要做一次，并养成&#8220;先同步 后修改&#8221;的习惯，和Virvual SourceSafe不同，CVS里没有文件锁定的概念，所有的冲突是在commit之前解决，如果你修改过程中，有其他人修改并commit到了CVS 库中，CVS会通知你文件冲突，并自动将冲突部分用<br />
&gt;&gt;&gt;&gt;&gt;&gt;<br />
content on cvs server<br />
&lt;&lt;&lt;&lt;&lt;&lt;<br />
content in your file<br />
&gt;&gt;&gt;&gt;&gt;&gt;<br />
标记出来，由你确认冲突内容的取舍。<br />
版本冲突一般是在多个人修改一个文件造成的，但这种项目管理上的问题不应该指望由CVS来解决。</em></p>
<p><u>确认修改写入到CVS库里</u><br />
cvs commit -m "write some comments here" file_name</p>
<p><em>注意：CVS的很多动作都是通过cvs commit进行最后确认并修改的，最好每次只修改一个文件。在确认的前，还需要用户填写修改注释，以帮助其他开发人员了解修改的原因。如果不用写-m "comments"而直接确认`cvs commit file_name` 的话，cvs会自动调用系统缺省的文字编辑器(一般是vi)要求你写入注释。<br />
注释的质量很重要：所以不仅必须要写，而且必须写一些比较有意义的内容：以方便其他开发人员能够很好的理解<br />
不好的注释，很难让其他的开发人员快速的理解：比如： -m "bug fixed" 甚至 -m ""<br />
好的注释，甚至可以用中文: -m "在用户注册过程中加入了Email地址校验"</em> <br />
<br />
修改某个版本注释：每次只确认一个文件到CVS库里是一个很好的习惯，但难免有时候忘了指定文件名，把多个文件以同样注释commit到CVS库里了，以 下命令可以允许你修改某个文件某个版本的注释：<br />
cvs admin -m 1.3:"write some comments here" file_name<br />
<br />
<u>添加文件</u><br />
创建好新文件后，比如：touch new_file<br />
cvs add new_file<br />
<em>注意：对于图片，Word文档等非纯文本的项目，需要使用cvs add -kb选项按2进制文件方式导入(k表示扩展选项，b表示binary)，否则有可能出现文件被破坏的情况<br />
比如：<br />
cvs add -kb new_file.gif<br />
cvs add -kb readme.doc</em></p>
<p><em>如果关键词替换属性在首次导入时设置错了怎么办？<br />
</em>cvs admin -kkv new_file.css <br />
<em><br />
</em><span style="text-decoration: underline">然后确认修改并注释</span><br />
cvs ci -m "write some comments here"</p>
<p><u>删除文件</u><br />
将某个源文件物理删除后，比如：rm file_name<br />
cvs rm file_name<br />
然后确认修改并注释<br />
cvs ci -m "write some comments here"<br />
以上面前2步合并的方法为：<br />
cvs rm -f file_name<br />
cvs ci -m "why delete file"<br />
<em>注意：很多cvs命令都有缩写形式：commit=&gt;ci; update=&gt;up; checkout=&gt;co/get; remove=&gt;rm;</em> </p>
<p><u>添加目录</u><br />
cvs add dir_name<br />
<br />
<u>查看修改历史</u><br />
cvs log file_name<br />
cvs history file_name<br />
<br />
<u>查看当前文件不同版本的区别</u><br />
cvs diff -r1.3 -r1.5 file_name<br />
查看当前文件（可能已经修改了）和库中相应文件的区别<br />
cvs diff file_name<br />
cvs的web界面提供了更方便的定位文件修改和比较版本区别的方法，具体安装设置请看后面的cvsweb使用</p>
<p><u>正确的通过CVS恢复旧版本的方法</u>：<br />
如果用cvs update -r1.2 file.name<br />
这个命令是给file.name加一个STICK TAG： "1.2" ，虽然你的本意只是想将它恢复到1.2版本<br />
正确的恢复版本的方法是：cvs update -p -r1.2 file_name &gt;file_name<br />
如果不小心已经加成STICK TAG的话：用cvs update -A 解决</p>
<p><u>移动文件/文件重命名</u><br />
cvs里没有cvs move或cvs rename，因为这两个操作是可以由先cvs remove old_file_name，然后cvs add new_file_name实现的。</p>
<p><u>删除/移动目录</u><br />
最方便的方法是让管理员直接移动，删除CVSROOT里相应目录（因为CVS一个项目下的子目录都是独立的，移动到$CVSROOT目录下都可以作为新的 独立项目：好比一颗树，其实砍下任意一枝都能独立存活），对目录进行了修改后，要求其开发人员重新导出项目cvs checkout project_name 或者用cvs update -dP同步。</p>
<p><u>项目发布导出不带CVS目录的源文件</u><br />
做开发的时候你可能注意到了，每个开发目录下，CVS都创建了一个CVS/目录。里面有文件用于记录当前目录和CVS库之间的对应信息。但项目发布的时候 你一般不希望把文件目录还带着含有CVS信息的CVS目录吧，这个一次性的导出过程使用cvs export命令，不过export只能针对一个TAG或者日期导出，比如：<br />
cvs export -r release1 project_name <br />
cvs export -D 20021023 project_name<br />
cvs export -D now project_name</p>
<h2><a name="branch"></a>CVS Branch：项目多分支同步开发</h2>
确认版本里程碑：多个文件各自版本号不一样，项目到一定阶段，可以给所有文件统一指定一个阶段里程碑版本号，方便以后按照这个阶段里程碑版本号导出项目， 同时也是项目的多个分支开发的基础。<br />
<p>cvs tag release_1_0</p>
<p><u>开始一个新的里程碑</u>：<br />
cvs commit -r 2 标记所有文件开始进入2.x的开发</p>
<p><em>注意：CVS里的revsion和软件包的发布版本可以没有直接的关系。但所有文件使用和发布版本一致的版本号比较有助于维护。</em></p>
<p><u>版本分支的建立</u><br />
在开发项目的2.x版本的时候发现1.x有问题，但2.x又不敢用，则从先前标记的里程碑：release_1_0导出一个分支 release_1_0_patch<br />
cvs rtag -b -r release_1_0 release_1_0_patch proj_dir</p>
<p>一些人先在另外一个目录下导出release_1_0_patch这个分支：解决1.0中的紧急问题，<br />
cvs checkout -r release_1_0_patch<br />
而其他人员仍旧在项目的主干分支2.x上开发</p>
<p>在release_1_0_patch上修正错误后，标记一个1.0的错误修正版本号<br />
cvs tag release_1_0_patch_1</p>
<p>如果2.0认为这些错误修改在2.0里也需要，也可以在2.0的开发目录下合并release_1_0_patch_1中的修改到当前代码中：<br />
cvs update -j release_1_0_patch_1</p>
<h2><a name="ssh"></a>CVS的远程认证通过SSH远程访问CVS</h2>
使用cvs本身基于pserver的远程认证很麻烦,需要定义服务器和用户组，用户名，设置密码等，<br />
<p>常见的登陆格式如下：<br />
cvs -d :pserver:cvs_user_name@cvs.server.address:/path/to/cvsroot login<br />
例子：<br />
cvs -d :pserver:cvs@samba.org:/cvsroot login</p>
<p>不是很安全，因此一般是作为匿名只读CVS访问的方式。从安全考虑，通过系统本地帐号认证并通过SSH传输是比较好的办法，通过在客户机的 /etc/profile里设置一下内容：<br />
CVSROOT=:ext:$USER@cvs.server.address#port:/path/to/cvsroot CVS_RSH=ssh; export CVSROOT CVS_RSH<br />
所有客户机所有本地用户都可以映射到CVS服务器相应同名帐号了。</p>
<p>比如:</p>
<p>CVS服务器是192.168.0.3，上面CVSROOT路径是/home/cvsroot，另外一台开发客户机是192.168.0.4，如果 tom在2台机器上都有同名的帐号，那么从192.168.0.4上设置了：<br />
export CVSROOT=:ext:tom@192.168.0.3:/home/cvsroot<br />
export CVS_RSH=ssh<br />
tom就可以直接在192.168.0.4上对192.168.0.3的cvsroot进行访问了（如果有权限的话）<br />
cvs checkout project_name<br />
cd project_name<br />
cvs update<br />
...<br />
cvs commit <br />
</p>
<p>如果CVS所在服务器的SSH端口不在缺省的22，或者和客户端与CVS服务器端SSH缺省端口不一致，有时候设置了：<br />
:ext:$USER@test.server.address#port:/path/to/cvsroot <br />
<br />
仍然不行，比如有以下错误信息：<br />
ssh: test.server.address#port: Name or service not known<br />
cvs [checkout aborted]: end of file from server (consult above messages if any)<br />
<br />
解决的方法是做一个脚本指定端口转向（不能使用alias，会出找不到文件错误）：<br />
创建一个/usr/bin/ssh_cvs文件，假设远程服务器的SSH端口是非缺省端口：34567<br />
#!/bin/sh<br />
/usr/bin/ssh -p 34567 "$@"<br />
然后：chmod +x /usr/bin/ssh_cvs<br />
并CVS_RSH=ssh_cvs; export CVS_RSH</p>
<p>注意：port是指相应服务器SSH的端口，不是指cvs专用的pserver的端口<br />
<br />
</p>
<h2><a name="cvsweb"></a>CVSWEB：提高文件浏览效率</h2>
CVSWEB就是CVS的WEB界面，可以大大提高程序员定位修改的效率:<br />
<p>使用的样例可以看：<a href="http://www.freebsd.org/cgi/cvsweb.cgi">http://www.freebsd.org/cgi/cvsweb.cgi</a></p>
<p>CVSWEB的下载：CVSWEB从最初的版本已经演化出很多功能界面更丰富的版本，这个是我个人感觉安装设置比较方便的：<br />
原先在：http://www.spaghetti-code.de/software/linux/cvsweb/，但目前已经删除，<a href="http://www.chedong.com/cgi-bin/mt/cvsweb.tgz">目前仍可以在本站下载CVSWEB</a>， 其实最近2年<a href="http://www.freebsd.org/projects/cvsweb.html">FreeBSD的CVSWeb项目</a>已经有了更好的发展吧，而当初没有用FreeBSD那个版本 主要就是因为没有彩色的文件Diff功能。 <br />
下载解包：<br />
tar zxf cvsweb.tgz<br />
把配置文件cvsweb.conf放到安全的地方（比如和apache的配置放在同一个目录下），<br />
修改：cvsweb.cgi让CGI找到配置文件：<br />
$config = $ENV{'CVSWEB_CONFIG'} || '/path/to/apache/conf/cvsweb.conf';<br />
<br />
转到/path/to/apache/conf下并修改cvsweb.conf：</p>
<ol>
    <li>修改CVSROOT路径设置：<br />
    %CVSROOT = (<br />
    'Development' =&gt; '/path/to/cvsroot', #&lt;==修改指向本地的CVSROOT<br />
    );
    <li>缺省不显示已经删除的文档：<br />
    "hideattic" =&gt; "1",#&lt;==缺省不显示已经删除的文档
    <li>在配置文件cvsweb.conf中还可以定制页头的描述信息，你可以修改$long_intro成你需要的文字 </li>
</ol>
<p>CVSWEB可不能随便开放给所有用户，因此需要使用WEB用户认证：<br />
先生成 passwd:<br />
/path/to/apache/bin/htpasswd -c cvsweb.passwd user<br />
<br />
修改httpd.conf: 增加<br />
&lt;Directory "/path/to/apache/cgi-bin/cvsweb/"&gt;<br />
AuthName "CVS Authorization"<br />
AuthType Basic<br />
AuthUserFile /path/to/cvsweb.passwd<br />
require valid-user<br />
&lt;/Directory&gt;<br />
<br />
</p>
<h2><a name="tag"></a>CVS TAGS: $Id$</h2>
将$Id$ 加在程序文件开头的注释里是一个很好的习惯，cvs能够自动解释更新其中的内容成：file_name version time user_name 的格式，比如：cvs_card.txt,v 1.1 2002/04/05 04:24:12 chedong Exp，可以这些信息了解文件的最后修改人和修改时间。<br />
<pre>几个常用的缺省文件：<br />
default.php<br />
&lt;?php<br />
/*<br />
* Copyright (c) 2002 Company Name.<br />
* $Header$<br />
*/<br />
<br />
?&gt;<br />
====================================<br />
Default.java: 注意文件头一般注释用 /* 开始 JAVADOC注释用 /** 开始的区别<br />
/*<br />
* Copyright (c) 2002 MyCompany Name.<br />
* $Header$<br />
*/<br />
<br />
package com.mycompany;<br />
<br />
import java.;<br />
<br />
/**<br />
* comments here<br />
*/<br />
public class Default {<br />
/**<br />
* Comments here<br />
* @param<br />
* @return<br />
*/<br />
public toString() {<br />
<br />
}<br />
}<br />
====================================<br />
default.pl:<br />
#!/usr/bin/perl -w<br />
# Copyright (c) 2002 Company Name.<br />
# $Header$<br />
<br />
# file comments here<br />
<br />
use strict;<br />
<br />
</pre>
<h2><a name="vss"></a>CVS vs VSS</h2>
<p>CVS没有文件锁定模式，VSS在check out同时，同时记录了文件被导出者锁定。 </p>
<p>CVS的update和commit， VSS是get_lastest_version和check in </p>
<p>对应VSS的check out/undo check out的CVS里是edit和unedit </p>
<p>在CVS中，标记自动更新功能缺省是打开的，这样也带来一个潜在的问题，就是不用-kb方式添加binary文件的话在cvs自动更新时可能会导致 文件失效。</p>
<p>$Header$ $Date$这样的标记在Virsual SourceSafe中称之为Keyword Explaination，缺省是关闭的，需要通过OPITION打开，并指定需要进行源文件关键词扫描的文件类型：*.txt,*.java, *.html...</p>
<p>对于Virsual SourceSafe和CVS都通用的TAG有：<br />
$Header$<br />
$Author$<br />
$Date$ <br />
$Revision$ </p>
<p>我建议尽量使用通用的关键词保证代码在CVS和VSS都能方便的跟踪。 </p>
<h2><a name="wincvs"></a>WinCVS</h2>
下载：<br />
<p>cvs Windows客户端：目前稳定版本为1.2<br />
<a href="http://cvsgui.sourceforge.net/">http://cvsgui.sourceforge.net</a><br />
ssh Windows客户端<br />
<a href="http://www.networksimplicity.com/openssh/">http://www.networksimplicity.com/openssh/</a><br />
<br />
安装好以上2个软件以后：<br />
WinCVS客户端的admin==&gt;preference设置<br />
1 在general选单里<br />
设置CVSROOT： username@192.168.0.123:/home/cvsroot<br />
设置Authorization: 选择SSH server<br />
<br />
2 Port选单里<br />
钩上：check for alternate rsh name<br />
并设置ssh.exe的路径，缺省是装在 C:\Program Files\NetworkSimplicity\ssh\ssh.exe </p>
<p>然后就可以使用WinCVS进行cvs操作了，所有操作都会跳出命令行窗口要求你输入服务器端的认证密码。 </p>
<p>当然，如果你觉得这样很烦的话，还有一个办法就是生成一个没有密码的公钥/私钥对，并设置CVS使用基于公钥/私钥的SSH认证（在general 选单里）。</p>
<p>可以选择的diff工具：examdiff<br />
下载：<br />
<a href="http://www.prestosoft.com/examdiff/examdiff.htm">http://www.prestosoft.com/examdiff/examdiff.htm</a><br />
还是在WinCVS菜单admin==&gt;preference的WinCVS选单里<br />
选上：Externel diff program<br />
并设置diff工具的路径，比如：C:\Program Files\ed16i\ExamDiff.exe<br />
在对文件进行版本diff时，第一次需要将窗口右下角的use externel diff选上。 </p>
<h2><a name="cvstrac"></a>基于CVSTrac的小组开发环境搭建</h2>
作为一个小组级的开发环境，版本控制系统和BUG跟踪系统等都涉及到用户认证部分。如何方便的将这些系统集成起来是一个非常困难的事情，毕竟我们不能指望 Linux下有像Source Offsite那样集成度很高的版本控制/BUG跟踪集成系统。<br />
<br />
我个人是很反对使用pserver模式的远程用户认证的，但如果大部分组员使用WINDOWS客户端进行开发的话，总体来说使用 CVSROOT/passwd认证还是很难避免的，但CVS本身用户的管理比较麻烦。本来我打算自己用perl写一个管理界面的，直到我发现了 CVSTrac： 一个基于WEB界面的BUG跟踪系统，它外挂在CVS系统上的BUG跟踪系统，其中就包括了WEB界面的CVSROOT/passwd文件的管理，甚至还 集成了WIKIWIKI讨论组功能。
<p>这里首先说一下CVS的pserver模式下的用户认证，CVS的用户认证服务是基于inetd中的：<br />
cvspserver stream tcp nowait apache /usr/bin/cvs cvs --allow-root=/home/cvsroot pserver<br />
一般在2401端口（这个端口号很好记：49的平方）<br />
<br />
CVS用户数据库是基于CVSROOT/passwd文件，文件格式：<br />
[username]:[crypt_password]:[mapping_system_user]<br />
由于密码都用的是UNIX标准的CRYPT加密，这个passwd文件的格式基本上是apache的htpasswd格式的扩展（比APACHE的 PASSWD文件多一个系统用户映射字段），所以这个文件最简单的方法可以用<br />
apache/bin/htpasswd -b myname mypassword <br />
创建。注意：通过htpasswd创建出来的文件会没有映射系统用户的字段<br />
例如：<br />
new:geBvosup/zKl2<br />
setup:aISQuNAAoY3qw<br />
test:hwEpz/BX.rEDU </p>
<p>映射系统用户的目的在于：你可以创建一个专门的CVS服务帐号，比如用apache的运行用户apache，并将/home/cvsroot目录下 的所有权限赋予这个用户，然后在passwd文件里创建不同的开发用户帐号，但开发用户帐号最后的文件读写权限都映射为apache用户，在SSH模式下 多个系统开发用户需要在同一个组中才可以相互读写CVS库中的文件。</p>
<p>进一步的，你可以将用户分别映射到apache这个系统用户上。<br />
new:geBvosup/zKl2:apache<br />
setup:aISQuNAAoY3qw:apache<br />
test:hwEpz/BX.rEDU:apache </p>
<p>CVSTrac很好的解决了CVSROOT/passwd的管理问题，而且包含了BUG跟踪报告系统和集成WIKIWIKI交流功能等，使用的 CGI方式的安装，并且基于<a href="http://www.gnu.org/copyleft/gpl.html">GNU Public License</a>：<br />
</p>
<p align="left">在inetd里加入cvspserver服务：<br />
cvspserver stream tcp nowait apache /usr/bin/cvs cvs --allow-root=/home/cvsroot pserver</p>
<p align="left">xietd的配置文件：%cat cvspserver <br />
service cvspserver<br />
{<br />
disable = no<br />
socket_type = stream<br />
wait = no<br />
user = apache<br />
server = /usr/bin/cvs<br />
server_args = -f --allow-root=/home/cvsroot pserver<br />
log_on_failure += USERID<br />
}</p>
<p>注意：这里的用户设置成apache目的是和/home/cvsroot的所有用户一致，并且必须让这个这个用户对/home/cvsroot/下的 CVSROOT/passwd和cvstrac初始化生成的myproj.db有读取权限。</p>
<p>&nbsp;</p>
<p>安装过程 </p>
<ol>
    <li>下载：可以从<a href="http://www.cvstrac.org/">http://www.cvstrac.org</a> 下载<br />
    我用的是已经在Linux上编译好的应用程序包：cvstrac-1.1.2.bin.gz，<br />
    %gzip -d cvstrac-1.1.2.bin.gz<br />
    %chmod +x cvstrac-1.1.2.bin<br />
    #mv cvstarc-1.1.1.bin /usr/bin/cvstrac <br />
    如果是从源代码编译：<br />
    从 http://www.sqlite.org/download.html 下载SQLITE的rpm包：<br />
    rpm -i sqlite-devel-2.8.6-1.i386.rpm<br />
    从 ftp://ftp.cvstrac.org/cvstrac/ 下载软件包<br />
    解包，假设解包到/home/chedong/cvstrac-1.1.2下，并规划将cvstrac安装到/usr/local/bin目录下， cd /home/chedong/cvstrac-1.1.2 编辑linux-gcc.mk:<br />
    修改：<br />
    SRCDIR = /home/chedong/cvstrac-1.1.2<br />
    INSTALLDIR = /usr/local/bin<br />
    然后<br />
    mv linux-gcc.mk Makefile<br />
    make<br />
    #make install<br />
    <br />
    <li>初始化cvstrac数据库：假设数据库名是 myproj<br />
    在已经装好的CVS服务器上（CVS库这时候应该已经是初始化好了，比如：cvs init初始化在/home/cvsroot里），运行一下<br />
    %cvstrac init /home/cvsroot myproj<br />
    运行后，/home/cvsroot里会有一个的myproj.db库，使用CVSTRAC服务，/home/cvsroot/myproj.db /home/cvsroot/CVSROOT/readers /home/cvsroot/CVSROOT/writers /home/cvsroot/CVSROOT/passwd这几个文件对于web服务的运行用户应该是可写的，在RedHat8上，缺省就有一个叫 apache用户和一个apache组，所以在httpd.conf文件中设置了用apache用户运行web服务：<br />
    User apache<br />
    Group apache，<br />
    然后设置属于apache用户和apache组<br />
    #chown -R apache:apache /home/cvsroot<br />
    -rw-r--r-- 1 apache apache 55296 Jan 5 19:40 myproj.db<br />
    drwxrwxr-x 3 apache apache 4096 Oct 24 13:04 CVSROOT/<br />
    drwxrwxr-x 2 apache apache 4096 Aug 30 19:47 some_proj/<br />
    此外还在/home/cvsroot/CVSROOT中设置了：<br />
    chmod 664 readers writers passwd<br />
    <li>在apche/cgi-bin目录中创建脚本cvstrac:<br />
    #!/bin/sh<br />
    /usr/bin/cvstrac cgi /home/cvsroot<br />
    设置脚本可执行：<br />
    chmod +x /home/apache/cgi-bin/cvstrac<br />
    <li>从 http://cvs.server.address/cgi-bin/cvstrac/myproj 进入管理界面<br />
    缺省登录名：setup 密码 setup<br />
    对于一般用户可以从：<br />
    http://cvs.server.address/cgi-bin/cvstrac/myproj
    <li>在setup中重新设置了CVSROOT的路径后，/home/cvsroot<br />
    如果是初次使用需要在/home/cvsroot/CVSROOT下创建passwd, readers, writers文件<br />
    touch passwd readers writers<br />
    然后设置属于apache用户，<br />
    chown apache.apache passwd readers writers<br />
    这样使用setup用户创建新用户后会同步更新CVSROOT/passwd下的帐号<br />
    </li>
</ol>
<p align="left">修改登录密码，进行BUG报告等，<br />
更多使用细节可以在使用中慢慢了解。<br />
</p>
<p align="left">对于前面提到的WinCVS在perference里设置：<br />
CVSROOT栏输入：username@ip.address.of.cvs:/home/cvsroot<br />
Authenitication选择：use passwd file on server side <br />
就可以了从服务器上进行CVS操作了。<br />
</p>
<h2><a name="auth"></a>CVS的用户权限管理</h2>
<p align="left">CVS的权限管理分2种策略：<br />
</p>
<ul>
    <li>基于系统文件权限的系统用户管理：适合多个在Linux上使用系统帐号的开发人员进行开发。
    <li>基于CVSROOT/passwd的虚拟用户管理：适合多个在Windows平台上的开发人员将帐号映射成系统帐号使用。 </li>
</ul>
为什么使用apache/apache用户？首先RedHat8中缺省就有了，而且使用这个用户可以方便通过cvstrac进行WEB管理。<br />
chown -R apache.apache /home/cvsroot<br />
chmod 775 /home/cvsroot<br />
<p align="left">Linux上通过ssh连接CVS服务器的多个开发人员：通过都属于apache组实现文件的共享读写<br />
开发人员有开发服务器上的系统帐号：sysuser1 sysuser2，设置让他们都属于apache组，因为通过cvs新导入的项目都是对组开放的：664权限的，这样无论那个系统用户导入的项目文件，只 要文件的组宿主是apache，所有其他同组系统开发用户就都可以读写；基于ssh远程认证的也是一样。<br />
</p>
<p align="left">&nbsp; &nbsp;apache(system group)<br />
/ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \<br />
sysuser1 &nbsp; sysuser2 &nbsp; &nbsp; sysuser3<br />
</p>
<p align="left">Windows上通过cvspserver连接CVS服务器的多个开发人员：通过在passwd文件种映射成 apache用户实现文件的共享读写<br />
他们的帐号通过CVSROOT/passwd和readers writers这几个文件管理；通过cvstrac设置所有虚拟用户都映射到apache用户上即可。<br />
</p>
<p align="left">&nbsp; &nbsp;apache(system user)<br />
/ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\<br />
windev1 &nbsp; &nbsp; windev2 &nbsp; &nbsp; &nbsp;windev3&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</p>
<p align="left">&nbsp;</p>
<p>&nbsp;</p>
<p>利用CVS WinCVS/CVSWeb/CVSTrac 构成了一个相对完善的跨平台工作组开发版本控制环境。</p>
<p>相关资源： </p>
<p>CVS HOME：<br />
<a href="http://www.cvshome.org/">http://www.cvshome.org</a></p>
<p>CVS FAQ：<br />
<a href="http://www.loria.fr/%7Emolli/cvs-index.html">http://www.loria.fr/~molli/cvs-index.html</a><br />
<br />
相关网站:<br />
<a href="http://directory.google.com/Top/Computers/Software/Configuration_Management/Tools/Concurrent_Versions_System/">http://directory.google.com/Top/Computers/Software/Configuration_Management/Tools/Concurrent_Versions_System/</a><br />
</p>
<p>CVS--并行版本系统<br />
<a href="http://www.soforge.com/cvsdoc/zh_CN/book1.html">http://www.soforge.com/cvsdoc/zh_CN/book1.html</a></p>
<p>CVS 免费书:<br />
<a href="http://cvsbook.red-bean.com/">http://cvsbook.red-bean.com/</a></p>
<p><a href="http://refcards.com/refcards/cvs/index.html">CVS命令的速查卡片 refcards.com/refcards/cvs/</a></p>
<p>WinCVS:<br />
<a href="http://cvsgui.sourceforge.net/">http://cvsgui.sourceforge.net/</a></p>
<p>CVSTrac: A Web-Based Bug And Patch-Set Tracking System For CVS<br />
<a href="http://www.cvstrac.org/">http://www.cvstrac.org</a> </p>
<p>StatCVS：基于CVS的代码统计工具：按代码量，按开发者的统计表等<br />
<a href="http://sourceforge.net/projects/statcvs">http://sourceforge.net/projects/statcvs<br />
</a></p>
如何在WEB开发中规划CVS上：在Google上查 "cvs web development"<br />
<a href="http://ccm.redhat.com/bboard-archive/cvs_for_web_development/index.html">http://ccm.redhat.com/bboard-archive/cvs_for_web_development/index.html</a><br />
<br />
一些集成了CVS的IDE环境： <br />
<a href="http://www.eclipse.org/">Eclipse</a><br />
</div>
</div>
<img src ="http://www.blogjava.net/conans/aggbug/210985.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-26 23:39 <a href="http://www.blogjava.net/conans/articles/210985.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CVS使用经验谈</title><link>http://www.blogjava.net/conans/articles/210983.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Thu, 26 Jun 2008 15:38:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/210983.html</guid><description><![CDATA[CVS 是 Concurrent Version System（并行版本系统）的缩写，用于版本管理。在多人团队开发中的作用更加明显。CVS 的基本工作思路是这样的：在一台服务器上建立一个仓库，仓库里可以存放许多不同项目的源程序。由仓库管理员统一管理这些源程序。这样，就好象只有一个人在修改文件一样。避免了冲突。每个用户在使用仓库之前，首先要把仓库里的项目文件下载到本地。用户做的任何修改首先都是在本地进行，然后用 cvs 命令进行提交，由 cvs 仓库管理员统一 修改。这样就可以做到跟踪文件变化，冲突控制等等。
<div class="tbody">
<p>CVS 是 Concurrent Version System（并行版本系统）的缩写，用于版本管理。在多人团队开发中的作用更加明显。CVS 的基本工作思路是这样的：在一台服务器上建立一个仓库，仓库里可以存放许多不同项目的源程序。由仓库管理员统一管理这些源程序。这样，就好象只有一个人在修改文件一样。避免了冲突。每个用户在使用仓库之前，首先要把仓库里的项目文件下载到本地。用户做的任何修改首先都是在本地进行，然后用 cvs 命令进行提交，由 cvs 仓库管理员统一 修改。这样就可以做到跟踪文件变化，冲突控制等等。
<p>　　由于CVS是建立在在原先 Unix 体系里很成熟的 SCCS 和 RCS 的基础上，所以CVS多是Linux（UNIX）系统中所使用，本文中服务器端设置也是以Linux为例。</p>
<p>　　一、CVS服务器的安装</p>
<p>　　首先确认系统中是否安装CVS服务：<br />
　　 [root@localhost /]# rpm -qa|grep cvs<br />
cvs-1.11.2-cvshome.7x.1<br />
　　 如果命令输出类似于上面的输出则说明系统已经安装有cvs，否则就需要从安装光盘中安装cvs的rpm包，或者到http://www.cvshome.org下载。</p>
<p>　　1、建立 CVSROOT</p>
<p>　　目录，因为这里涉及到用户对CVSROOT里的文件读写的权限问题，所以比较简单的方法是建立一个组，然后再建立一个属于该组的帐户，而且以后有读写权限的用户都要属于该组。假设我们建一个组叫cvs，用户名是cvsroot。建组和用户的命令如下</p>
<p>#groupadd cvs<br />
#adduser cvsroot</p>
<p>　　生成的用户宿主目录在/home/cvsroot（根据自己的系统调整）</p>
<p>　　2、用cvsroot 用户登陆，修改 /home/cvsroot （CVSROOT）的权限，赋与同组人有读写的权限：　</p>
<p>　　$chmod 771 . （或者770应该也可以）</p>
<p>　　注意：这一部分工作是按照文档说明做的，是否一定需要这样没有试验，我会在做试验后在以后版本的教程说得仔细一点。如果您有这方面的经验请提供给我，谢谢。</p>
<p>　　3、建立CVS仓库，（仍然是 cvsroot 用户），用下面命令：</p>
<p>　　$cvs -d /home/cvsroot init</p>
<p>　　4、以root身份登陆，修改 /etc/inetd.conf（使用 xinetd 的系统没有此文件）和 /etc/services</p>
<p>　　如果用的是 inetd 的系统，在 /etc/inetd.conf 里加入：<br />
　　 <br />
　　 cvsserver　 stream tcp nowait root /usr/bin/cvs cvs -f --allow-root=/home/cvsroot pserver</p>
<p>　　说明：上面的行是单独一整行，/usr/bin/cvs 应该是你的cvs版本的命令路径，请根据自己的系统调整．/home/cvsroot是你建立的CVSROOT的路径，也请根据上面建立目录的部分的内容做调整。</p>
<p>　　如果是使用 xinetd 的系统，需要在 /etc/xinetd.d/ 目录下创建文件 cvspserver（此名字可以自己定义），内容如下：</p>
<p>　　# default: on<br />
　　 # description: The cvs server sessions;</p>
<p>　　service cvsserver<br />
　　 {<br />
　　 socket_type = stream<br />
　　 wait = no<br />
　　 user = root<br />
　　 server = /usr/bin/cvs<br />
　　 server_args = -f --allow-root=/cvsroot pserver<br />
　　 log_on_failure += USERID<br />
　　 only_from = 192.168.0.0/24<br />
　　 }</p>
<p>　　其中only_from是用来限制访问的，可以根据实际情况不要或者修改。修改该文件权限：</p>
<p>　　# chmod 644 cvspserver</p>
<p>　　在/etc/services里加入：</p>
<p>　　cvsserver 2401/tcp</p>
<p>　　说明：cvsserver 是任意的名称，但是不能和已有的服务重名，也要和上面修改 /etc/inetd.conf 那行的第一项一致。</p>
<p>　　5、添加可以使用 CVS 服务的用户到 cvs 组：</p>
<p>　　以 root 身份修改 /etc/group，把需要使用 CVS 的用户名加到 cvs 组里，比如我想让用户 laser 和gumpwu 能够使用 CVS 服务，那么修改以后的 /etc/group 应该有下面这样一行：</p>
<p>　　cvs:x:105:laser,gumpwu</p>
<p>　　在你的系统上GID可能不是105，没有关系。主要是要把laser和gumpwu用逗号分隔开写在最后一个冒号后面。当然，象RedHat等分发版有类似linuxconf这样的工具的话，用工具做这件事会更简单些。</p>
<p>　　6、重起inetd使修改生效：</p>
<p>　　#killall -HUP inetd</p>
<p>　　如果使用的是 xinetd 的系统：<br />
<br />
　　 # /etc/rc.d/init.d/xined restart</p>
<p>然后察看cvs服务器是否已经运行：<br />
[root@localhost /]# netstat -lnp|grep 2401<br />
　　 tcp 0 0 0.0.0.0:2401 0.0.0.0:* LISTEN 1041/xinetd<br />
则说明cvs服务器已经运行。</p>
<p><br />
　　 二、管理CVS服务器</p>
<p>　　服务器可以用了，现在大家最关心的就是如何管理服务器，比如，我想让一些人有读和/或写 CVS 仓库的权限，但是不想给它系统权限怎么办呢？</p>
<p>　　不难，在 cvs 管理员用户（在我这里是 cvsroot 用户）的家目录里有一个 CVSROOT 目录，这个目录里有三个配置文件，passwd, readers, writers，我们可以通过设置这三个文件来配置 CVS 服务器，下面分别介绍这几个文件的作用：</p>
<p>　　passwd：cvs 用户的用户列表文件，它的格式很象 shadow 文件：</p>
<p>　　{cvs 用户名}:[加密的口令]:[等效系统用户名]</p>
<p>　　如果你希望一个用户只是 cvs 用户，而不是系统用户，那么你就要设置这个文件，刚刚安装完之后这个文件可能不存在，你需要以 cvs 管理员用户手工创建，当然要按照上面格式，第二个字段是该用户的加密口令，就是用 crypt (3)加密的，你可以自己写一个程序来做加密，也可以用我介绍的偷懒的方法：先创建一个系统用户，名字和 cvs 用户一样，口令就是准备给它的 cvs 用户口令，创建完之后从 /etc/shadow 把该用户第二个字段拷贝过来，然后再把这个用户删除。这个方法对付数量少的用户比较方便，人一多就不合适了，而且还有冲突条件(race condition)的安全隐患，还要 root 权限，实在不怎么样。不过权益之计而已。写一个小程序并不难，可以到 linuxforum 的编程版搜索一下，有个朋友已经写了一个贴在上面了。</p>
<p>　　第三个字段就是等效系统用户名，实际上就是赋与一个 cvs 用户一个等效的系统用户的权限，看下面的例子你就明白它的功能了。</p>
<p>　　readers：有 cvs 读权限的用户列表文件。就是一个一维列表。在这个文件中的用户对 cvs只有读权限。</p>
<p>　　writers：有 cvs 写权限的用户的列表文件。和 readers 一样，是一个一维列表。在这个文件中的用户对 cvs 有写权限。</p>
<p>　　上面三个文件在缺省安装的时候可能都不存在，需要我们自己创建，好吧，现在还是让我们用一个例子来教学吧。假设我们有下面几个用户需要使用 cvs：</p>
<p>　　laser, gumpwu, henry, betty, anonymous。</p>
<p>　　其中 laser 和 gumpwu 是系统用户，而 henry, betty, anonymous 我们都不想给系统用户权限，并且 betty 和 anonymous 都是只读用户，而且 anonymous 更是连口令都没有。那么好，我们先做一些准备工作，先创建一个 cvspub 用户，这个用户的责任是代表所有非系统用户的 cvs 用户读写 cvs 仓库。</p>
<p>　　#adduser<br />
　　 ...</p>
<p>　　然后编辑 /etc/group，令 cvspub 用户在 cvs 组里，同时把其它有系统用户权限的用户加到 cvs 组里。（见上文）</p>
<p>　　然后编辑 cvs 管理员家目录里 CVSROOT/passwd 文件，加入下面几行：</p>
<p>　　laser:$xxefajfka;faffa33:cvspub<br />
　　 gumpwu:$ajfaal;323r0ofeeanv:cvspub<br />
　　 henry:$fajkdpaieje:cvspub<br />
　　 betty:fjkal;ffjieinfn/:cvspub<br />
　　 anonymous::cvspub</p>
<p>　　注意：上面的第二个字段（分隔符为 :）是密文口令，你要用程序或者用我的土办法生成。</p>
<p>　　编辑 readers 文件，加入下面几行：</p>
<p>　　anonymous<br />
　　 betty</p>
<p>　　编辑 writers 文件，加入下面几行：</p>
<p>　　laser<br />
　　 gumpwu<br />
　　 henry</p>
<p>　　注意：writers中的用户不能在readers中，要不然不能上传更新文件。</p>
<p><br />
　　 对于使用CVS的用户要修改它的环境变量，例如laser用户的环境变量，打开/home/laser（laser的宿主目录）下的.bash_profile文件，加入</p>
<p>　　CVSROOT=/home/cvsroot<br />
　　 export CVSROOT</p>
<p>　　用laser登陆就可以建立CVS项目，如果要root使用，可以修改/etc/profile文件。</p>
<p><br />
　　 现在我们各项都设置好了，那么怎么用呢，我在这里写一个最简单的（估计也是最常用的）命令介绍：</p>
<p>　　首先，建立一个新的CVS项目，一般我们都已经有一些项目文件了，这样我们可以用下面步骤生成一个新的CVS项目：</p>
<p>　　进入到你的已有项目的目录，比如叫 cvstest：</p>
<p>　　$cd cvstest<br />
　　 运行命令：<br />
　　 $cvs import -m "this is a cvstest project" cvstest v_0_0_1 start</p>
<p>　　说明：import 是cvs的命令之一，表示向cvs仓库输入项目文件。 -m参数后面的字串是描述文本，随便写些有意义的东西，如果不加 -m 参数，那么cvs会自动运行一个编辑器（一般是vi，但是可以通过修改环境变量EDITOR来改成你喜欢用的编辑器。）让你输入信息，cvstest 是项目名称（实际上是仓库名，在CVS服务器上会存储在以这个名字命名的仓库里。）<br />
v_0_0_1是这个分支的总标记。没啥用（或曰不常用。）<br />
start 是每次 import 标识文件的输入层次的标记，没啥用。<br />
这样我们就建立了一个CVS仓库了。</p>
<p>　　建立CVS仓库的文件夹应该是&#8220;干净&#8221;的文件夹，即只包括源码文件和描述的文件加，而不应该包括编译过的文件代码等！</p>
<p>　　三、使用CVS</p>
<p>　　winCVS是一个很好的CVS客户端软件，在http://cnpack.cosoft.org.cn/down/wincvsdailyguide.pdf可以下载到这个软件的使用手册。这里不在赘述了。</p>
<p>　　四、用CVS管理项目</p>
<p>　　本人正在一加公司从事该公司ERP项目的开发，在没有使用CVS的时候，多次出现了由于不同的开发人员修改同一程序，而导致程序错误，解决版本控制问题迫在眉睫。</p>
<p>　　由于这个项目采用Linux平台下JAVA开发，使用的开发工具Jbulider是支持CVS进行项目管理的，作为主程序员，我决定采用CVS进行版本控制，首先参照上文在Linux服务器上建立了CVS服务，然后我把我本地的工程文件传至服务器。</p>
<p>　　例如：我的工程文件在F:\ERP下，我把ERP下的erp.jpx文件、defaultroot文件夹和src文件夹上传至服务器/usr/local/erp下，然后登陆Linux服务器，登陆的用户是CVS的用户，其环境变量要正确（我的用户名为admin）</p>
<p>　　#cd /usr/local/erp<br />
　　 #cvs import -m "this is a ERP project" erp v_0_0_1 start</p>
<p>　　这样名为erp的CVS仓库就建立了。</p>
<p>　　之后开发小组的成员可以用winCVS把该项目下载到本地：</p>
<p>　　打开winCVS</p>
<p>　　点击工具栏Create -&gt; Create a new repository... 弹出窗口<br />
　　 在Grenral中<br />
　　 Enter the CVSROOT填写admin@192.168.1.9:/home/cvsroot 其中admin是cvs的用户，在本例中admin也是linux的系统用户，192.168.1.9是服务器的地址，/home/cvsroot是CVS的主目录，参考上文。<br />
　　 Authentication中选择"passwd file on the cvs server"<br />
　　 Use version中选择cvs 1.10 (Standard)</p>
<p>　　其它项默认即可。</p>
<p>　　确认后，点工具栏Admin --&gt; Login... 会提示输入密码，输入密码后，看看winCvs的状态栏。如果提示</p>
<p>　　*****CVS exited normally with code 0*****</p>
<p>　　表示登录正常。</p>
<p>　　点击工具栏Create --&gt; Checkout module...弹出对话框，其中的Checkout settings项中<br />
　　 Enter the module name and path on the server 填写erp，即我们建立的名为erp的CVS仓库<br />
　　 Local folder to checkout to 选择要下载到本地的目录，我选了F:\myerp</p>
<p>　　其它项目可以默认，确定后就可以下载到本地了，在F:\myerp\下会有一个erp文件夹，其文件结构和F:\erp下的文件结构是一样的。</p>
<p>　　用Jbulider打开F:\myerp\erp\下的erp.jpx文件，这个工程文件就可以使用了。</p>
<p>　　在Jbuilder的工具栏Team --&gt; Select Project VCS 弹出对话框，选择CVS</p>
<p>　　对于你要进行修改的文件，在Project View中点中该文件，然后点右键，探出快捷菜单，选择CVS --&gt; CVS Edit "xxxx.java（文件名）"</p>
<p>　　第一次使用可能会提示CVS服务器的密码。</p>
<p>　　在修改之前还要选择CVS --&gt; Update "xxxx.java（文件名）"</p>
<p>　　修改之后选择CVS --&gt; Commit "xxxx.java（文件名）"</p>
<p>　　这样，修改的文件就保存到CVS服务器了，Update的目的是下载、比较文件。每次在修改之前都Update，保持最新版本。</p>
<p>　　CVS在项目管理使用中确实起到了良好的效果，仔细研究CVS的命令，可以更好的发挥CVS在版本控制上的能力。</p>
<p>　　我的QQ是20896，欢迎大家来交流，也可以到我的论坛上讨论 http://www.laoer.com</p>
</div>
<img src ="http://www.blogjava.net/conans/aggbug/210983.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-26 23:38 <a href="http://www.blogjava.net/conans/articles/210983.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CVS根据文件扩展名判断文件类型Text/Binary </title><link>http://www.blogjava.net/conans/articles/209874.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Sun, 22 Jun 2008 10:40:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/209874.html</guid><description><![CDATA[<p>今天很失败，画了一个中午的Visio流程图，在CVS上提交的时候，提交是成功了，就是文件被破坏掉了，大小变成了1KB。仔细看了一下，原来是Visio的文件.vsd的被CVS识别成Text的了，但是我确定我添加这个文件的时候是按照Binary的方式来添加的啊。于是继续做实验，发现果然是，即使你按照Binary的方式添加，在提交完毕之后，就变成了Text方式了。</p>
<p>&nbsp;</p>
<p>于是查看CVS的文档，也就是-kb参数来设定文件的类型。我切换到命令行方式，还是一样，被识别成Text的了。</p>
<p>&nbsp;</p>
<p>于是想找一种方式，来解决这个问题，否则在之后的工作中会有麻烦的（其实PowerDesigner的文档.pdm的也存在这种情况，但是至少.pdm是真正的文本文件，即使发生了冲突，虽然几率较小，也是可以在文文本编辑器中修改回来，但是Visio就不一样了，.vsd可是真正的Binary的文档啊）。</p>
<p>&nbsp;</p>
<p>看到cvs文档上说，可以修改cvswrappers文件来设定扩展名对应的处理方式，是Text还是Binary的方式，因为CVS并不能准确判断你加入的文件的类型。</p>
<p>&nbsp;</p>
<p>1. 使用WinCVS客户端或者cvs.exe命令行工具检出CVSROOT这个Module，需要注意的是，这个Module的安全界别设置比较高，需要Administrator或者有Admin权限的用户才可以。可以登录到服务器查看一下CVSROOT\CVS\fileattr.xml</p>
<p>2. 修改cvswrappers文件，里面有简单的说明，在最后加入两行：</p>
<p>&nbsp;&nbsp;&nbsp; *.vsd -kb</p>
<p>&nbsp;&nbsp;&nbsp; *.pdm -kb</p>
<p>&nbsp;&nbsp;&nbsp; 如果是其它的CVS版本，参考cvswrappers文件注释部分的内容</p>
<p>3. Commit 文件 cvswrappers</p>
<p>&nbsp;</p>
<p>然后就可以添加.vsd的文件了，果然能够识别成Binary的了。</p>
<p>&nbsp;</p>
<p>上面描述的问题和解决办法是 CVSNT 2.5 版本的，</p>
<p>在CVSNT 2.0版本中，如果你Add文件时用Binary方式，那么之后的操作就是以Binary对待了。</p>
<p>其它版本没有环境测试了。</p>
<img src ="http://www.blogjava.net/conans/aggbug/209874.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-22 18:40 <a href="http://www.blogjava.net/conans/articles/209874.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>