SVN學習筆記

发表于:2007-07-04来源:作者:点击数: 标签:
Subversion系统 多年来,并发版本系统( CVS )一直是在Linux上管理代码或者文本的标准。作为基于RCS上建立但却允许多用户协作的系统而言,CVS记录所有文件的修改信息。这对于程序 开发 者、 网络 设计者和系统管理员而言,是非常有用的。 然而,CVS逐渐显示

Subversion 系统

多年来,并发版本系统(CVS)一直是在Linux上管理代码或者文本的标准。作为基于RCS上建立但却允许多用户协作的系统而言,CVS记录所有文件的修改信息。这对于程序开发者、网络设计者和系统管理员而言,是非常有用的。
然而,CVS逐渐显示出它的衰老,出现了相似的源代码管理软件。然而大多这种东西都是以牟利为主要目的的。
Subversion就是一种相对新鲜的源代码管理系统。虽然事实上它还在不断的反展之中,但是Subversion已经是一个非常稳定而且成熟的产品。它是一个全新的系统,其功能可以和CVS媲美,同时,它要比CVS更直观,更容易操作。本文就Subversion的安装和一些特殊功能作一个介绍。
安装服务器端

下载Apache和SVN源码包
从官方网站台下载httpd-2.0.52.tar.gz,subversion-1.1.1.tar.gz
(因为redhat 9默认安装的Apache没有并包含--enable-so选项,所以无法产生mod_dav_svn.没有这个模块,SVN就无法采用http方式运行,所以必须重新编译新的Apache)
以root身份执行:
#tar zxvf httpd-2.0.52.tar.gz
#cd httpd-2.0.52
#./configure --enable-dav --enable-so --enable-maintainer-mode
#make 
#make install
此时会产生/usr/local/apache2目录,接着执行:
#tar zxvf subversion-1.1.1.tar.gz
#./configure --with-apxs=/usr/local/apache2/bin/apxs
# rm /usr/local/lib/libsvn*
# make clean && make && make install

此时会自动在/usr/local/apache2/conf/httpd.conf添加
LoadModule dav_svn_module  modules/mod_dav_svn.so
安装完成后,运行svnserver --version确认版本为1.1.1。
SVN服务器安装结束.

安装客户机端

window客户机:
直接安装TortoiseSVN-1.1.1-UNICODE_svn-1.1.1.msi,方法同一般软件安装相同。
Linux客户机:
方法舆安装服务器相同。
(注意redhat 9默认安装的SVN版本为0.17.1,它的客户端命令svn无法舆新的SVN服务器通讯,必须重新安装)

建立仓库Repository 

Subversion 的档案库是个中央仓储, 用来存放任意数量项目的受版本控管资料,建立方法很简单
#svnadmin create path/to/repos
举个例子:
#svnadmin create /home/mysvn
#chown –R nobody /home/mysvn
运行服务器

 Subversion服务器有两种运行方式,一是可以作为Apache 2.0的一个模块, 以WebDAV/DeltaV协议与外界连通;另外,也可使用Subversion 自带的小型服务器程序svnserve。该程序使用的是自带的通讯协议,可以很容易地透过SSH以
以http方式运行
在/usr/local/apache2/conf/httpd.conf中加入:
<Location /svn/repository>
  DAV svn
  SVNPath /home/mysvn
</Location>
在服务器的浏览器中输入网址: 
http://localhost/svn/repository/
这时候,你会看到这样的显示:
 
这表明服务器已经以http方式正常运行了.
以svnserve方式运行
这种方式的运行又可以分为以下两种(这和vsftp有些相似)
1)standalone mode
直接运行 #svnserve –d
运行 lsof -i :3690可以看到SVN服务器已经在运行
2)x.netd mode
在/etc/xinetd.d/下生成svnserve文件,内容如下
service svnserve
{
disable = no
socket_type             = stream
protocol                 = tcp
wait                    = no
user                    = apache
server                  = /usr/local/bin/svnserve
server_args             = -i
}
编辑 /etc/services 檔,加入底下两行:
svnserve        3690/tcp                        # Subversion svnserve
svnserve        3690/udp                        # Subversion svnserve
重启xinetd服务,运行 lsof -i :3690可以看到SVN服务器已经在运行

客户机访问

客户机的访问方法舆服务器的运行方式有直接关系
window客户机:
1)服务器以http方式运行
安装完TortoiseSVN-1.1.1-UNICODE_svn-1.1.1.msi后,在你想工作的目录下点击右键,执行checkout,按上图输入即可。
 
2) 服务器以svnserve方式运行
同上的区别只是URL of repository变为 svn://svn服务器ip/home/mysvn
或者 svn+ssh://svn服务器ip/home/mysvn
(注意不是//svn服务器ip//svn/repository)
linux客户机:
1)服务器以http方式运行
执行 #svn checkout http: //svn服务器ip/svn/repository
2)服务器以svnserve方式运行
执行 #svn checkout svn://svn服务器ip/home/mysvn
或者 #svn checkout svn+ssh://svn服务器ip/home/mysvn

客户认证机制

这舆服务器的运行方式有关
服务器以http方式运行
比如我们想给 Sally 与 Harry 送交存取档案库的权限. 首先, 我们必须把它们加入到密码档案. 
# ### 第一次: 以 -c 建立档案
# htpasswd -c /etc/svn-auth-file harry
New password: ***** 
Re-type new password: *****
Adding password for user harry
# htpasswd /etc/svn-auth-file sally
New password: *******
Re-type new password: *******
Adding password for user sally
#
接着,在/usr/local/apache2/conf/httpd.conf的加入: 
<Location /svn/repository >
  DAV svn
  SVNPath /home/mycvs
  AuthType Basic
  AuthName "Subversion repository"
  AuthUserFile /etc/svn-auth-file
Require valid-user
</Location>
重新激活 Apache后,如果有人要访问SVN服务器,系统会要求他输入用户名和密码。 只有输入Sally 或Harry的用户名和相应的密码,才可以对档案库进行修改和访问

服务器以svnserve方式运行
默认下客户可以以匿名方式通过svn://方式任意访问档案库,为了限制其权限,比如只允许读操作,可以通过修改档案库conf子目录中的svnseve.conf文件来实现。
#vi /home/mysvn/conf/svnseve.conf
修改[general]字段下内容为:
anon-access = read
如果设为anon-access = none,则匿名用户不可以通过svn://方式访问档案库
为了实现用户认证,我们一般采用svn+ssh://访问机制。
首先在svnseve.conf文件设置anon-access = none禁止匿名用户通过svn://方式访问档案库,然后在其后加入
auth-access = write
auth-access 是限制有援权的使用者(使用svn+ssh:// 来登入) 的存取权限,我们设为是可以读写。
当用户通过svn+ssh://访问时,服务器会自动激活ssh认证机制,要求用户输入密码,对于window用户来说还需要安装第三方软件openssh,才可以采用这种机制
Hook scripts
挂勾 (hook) 是改动档案库时所触发的程序, 比如当你提交更动前,会先触发pre-commit,提交更动后,则会触发post-commit,我们可以利用hook来实现一些自动控制。档案库的hook 子目录中, 预设是放置各个档案库挂勾的模板:
post-commit.tmpl          
pre-revprop-change.tmpl
post-revprop-change.tmpl  
start-commit.tmpl
pre-commit.tmpl        
如果要使用这些hook,就必须把它的后缀名.tmpl去掉,拷贝为
post-commit          
pre-revprop-change
post-revprop-change  
start-commit
pre-commit
这里主要介绍pre-commit和post-commit(事实上它们就是在特定的情况下被触发的普通的shell程序,至于shell的内容由用户自己随意编写,但是要保证名称不能改动) 
pre-commit 
本挂勾执行的时间为异动完成之后, 送交之前.档案库会传递两个自变量给这个程序: 档案库的路径, 以及准备送交的异动名称. 如果程序传回一个非零的结束值, 送交会被中止, 而异动会被删除. 

如何应用pre-commit我们不妨举个例子:
假如有一个项目由Mail Team,Login Team和PHP Team三个Team共同通过SVN系统开发完成。当项目准备发布的时候,PM人员发现Mail功能方面存在一些 bug,需要Mail Team去修改,为了防止其它Team的人员修改系统,我们可以在任何改动档案库的企图之前用pre-commit去检查log message信息,(因为任何更动档案库的操作都必须提供log message信息,PM可以事先舆Mail Team约定好一个log message),如果舆pre-commit中设定的log message不相符,则不能提交更动。
pre-commit源程序如下:
#!/bin/sh
REPOS="$1"
TXN="$2"
SVNLOOK=/usr/local/bin/svnlook
$SVNLOOK log -t "$TXN" "$REPOS" | \
   grep –w "bug1234" > /dev/null || exit 1
exit 0
本例中的log message为”bug1234”,任何人想要提交更动就必须用 –m “bug1234”参数,采用-m “bug123”,-m “bug12345”都会提交失败。
post-commit 
本挂勾执行的时间是在异动送交, 新修订版被建立之后. 大多数的人用这个挂勾来寄出关于本次送交的电子邮件, 或是建立档案库的备份. 档案库会传递两个自变量给这个程序: 档案库的路径, 以及新建立的修订版号. 本程序的结束码会被忽略. 

Subversion 源码树的 tools/hook-script 目录中包含了一个 commit-email.pl 命令,可以用来寄送包含描述指定送交的电子邮件. 这个邮件包含了更动路径列表, 该送交所对应的记录讯息, 使用者, 送交的日期,以及一个以 GNU diff 样式表示的本次更动差异. 我们可以将这个程序舆post-commit这个hook搭配起来使用来实现档案库更动后自动mail给相关人员的功能。
post-commit源程序如下:
#!/bin/sh
REPOS="$1"
REV="$2"
commit-email.pl "$REPOS" "$REV" PM@yourdomain.com 
##需要指明commit-email.pl的绝对路径

特殊性质

除了对你的目录与档案进行版本控制之外, Subversion 还提供了一个接口, 可用来新增, 修改, 以及移除已纳入版本控制的目录与档案的版本控制描述资料. 我们称这个描述资料为性质,在这里我主要介绍以下几个比较重要的特殊性质
svn:mime-type
svn:mime-type 性质在 Subversion 中有很多作用. 除了作为储存档案的多用途网际网络邮件延伸语法 (MIME) 分类之外, 这个性质的内容还会决定几项 Subversion 的行为特征. 
举个例子, 如果 svn:mime-type 性质设为文字的 MIME 类别 , Subversion 会假设该档的内容是二进制(也就是人类看不懂的资料). Subversion 提供的功能中, 其中一项是在从服务器收到工作档的更新中, 依文字内容与文字列进行合并. 但是对含有二进制资料的档案, 根本就没有 “文字列” 的概念. 因此, Subversion 对这些档案在更新时, 不会试着进行内文合并. 它改用另一种方式。 
一般来说Subversion 在执行 svn import 与 svn add 子命令时, 会使用二进制侦测运算法的方式来协助使用者.但是如果 Subversion 猜错了, 或是你希望将 svn:mime-type 设定成更为明确的值(可能是 image/png)你都可以移除或是手动编辑这个性质. 
svn:ignore
svn:ignore 性质包含了档案样式的列表, Subversion 处理时会忽略. 它可以与执行时期设定的 global-ignores 选项一起工作, 以便在类似 svn status 的命令中过滤掉未纳入版本控制的目录与档案. 
我们知道新增的文件和目录必须透过 svn add 命令, 才会被纳入 Subversion 的管理. svn status 命令会将工作复本中未纳入版控制目录与档案显示出来. 
$ svn status calc
 M     calc/button.c
?      calc/calculator
?      calc/data.c
?      calc/debug_log
?      calc/debug_log.1

在这个范例中, 用?标注出来的文件就是未纳入版控制的档案.如果你不想每次执行 svn status 时, 都看到这些档案, 那幺svn:ignore 性质就是解决方案。你可以透过 svn propedit svn:ignore calc 对 calc 目录加上一些忽略样式. 举个例子,将以下的值作为 svn:ignore 性质的新内容: 
calculator
debug_log*
加上这个性质后再执行你的 svn status 输出便会不同:
$ svn status
 M     calc
 M     calc/button.c
?      calc/data.c
现在, 所有不想看到的东西都从输出中消失了! 


svn:keywords
Subversion 具有取代关键词(有关纳入版本控制档案的有用信息)进入档案内容的功能. 
举个例子, 假设你有个文件, 想要在里面显示最近一次修改的日期. 你可以把这个负担加诸文件的作者身上, 让他们每一次送交更动之前, 顺便添加最近一次修改日期的部份. 但是迟早有人会忘记这件事. 换个方式, 只要叫 Subversion 对 LastChangedDate 关键词进行关键词取代即可.
Subversion 定义了可用来进行取代的关键词列表. 这个列表包含了以下五个关键词: 
LastChangedDate 
LastChangedRevision 
LastChangedBy 
HeadURL 
Id 
如果只把关键词定位锚加进档案里的话, 什幺事也不会发生.要告诉 Subversion 是否该对某一个档案进行关键词取代,得使用svn:keywords这个性质。当它被设定时, 它会控制该档案哪个关键词应该被取代. 
举个例子, 假设你有一个纳入版本控制的档案, 名为 weather.txt, 看起来像这样: 
Here is the latest report from the front lines.
$LastChangedDate$
$Rev$
Cumulus clouds are appearing more frequently as summer approaches.
如果没有设定该档案的 svn:keywords 性质, Subversion 什幺事也不会作. 让我们开启关键词 LastChangedDate 的内容取代. 
$ svn propset svn:keywords "LastChangedDate Author" weather.txt
property `svn:keywords' set on 'weather.txt'
$
在你送交了这个性质更动之后, Subversion 会显示为: 
Here is the latest report from the front lines.
$LastChangedDate: 2002-07-22 21:42:37 -0700 (Mon, 22 Jul 2002) $
$Rev$
Cumulus clouds are appearing more frequently as summer approaches.
这样不管谁提交这个文件,都会在里面显示最近一次修改的日期。
svn:eol-style
除非另外指定版本控制档案的 svn:mime-type 性质, Subversion 会假设档案包含人类可读的资料.这对于列尾符号 (EOL) 是很不幸地, 因为不同的操作系统会使用不同的符号来表示一列的结尾. 举个例子, 一般用在 Windows 平台上的列尾符号是两个 ASCII 控制字符 :返回字符 (CR) 与换行字符 (LF). 但是 Unix 软件就只使用 LF 字符来表示一列的结尾.这样以来window客户提交的档案中的CR 字符在 linux客户端会显示成 ^M, 而linux客户提交的档案中CR 字符在 Windows 客户端会被忽略。结果将档案里的所有文字列合并成一个超长的文字列, 这是因为没有返回CRLF字符组合的存在来表示一个换行。 解决的方法是 svn:eol-style 性质. 当这个性质设定为native时, Subversion 会根据系统的类型来决定是否对该档案的结尾进行自动处理。. 
svn:externals
有的时候, 一个工作复本可能包含了数个不同来源的工作复本. 举个例子, 你可能想要有数个不同的目录, 各来自不同的档案库.我们可以通过svn:externals 性质来宣告这一对对应关系。内容是子目录对应至 Subversion 档案库 URL 的多行表格. 
$ svn propget svn:externals calc
third-party/sounds          http://sounds.red-bean.com/repos
third-party/skins           http://skins.red-bean.com/repositories/skinproj
third-paartyy/skins/toolkit   http://svn.red-bean.com/repos/skin-maker
当有人取出 calc 目录的工作复本, Subversion 还会继续取出在外部定义里的项目. 
$ svn checkout http://svn.example.com/repos/calc
A  calc
A  calc/Makefile
A  calc/integer.c
A  calc/button.c
Checked out revision 148.

Fetching external item into calc/third-party/sounds
A  calc/third-party/sounds/ding.ogg
A  calc/third-party/sounds/dong.ogg
A  calc/third-party/sounds/clang.ogg
Checked out revision 14.

Fetching external item into calc/third-party/skins


小结

Subversion有一份很好的文檔——《Version Control with Subversion》(http://svnbook.red-bean.com/)。它提供了有关Subversion的各方面内容,如使用、管理和开发等。 
经过数年的开发,以替代CVS为目标的Subversion,相信以其强大的功能,对CVS良好的继承性,一定会有很好的发展。

作者简介
姓名:雷凯
工作单位:升技主板(苏州)研发中心
联系地址:苏州市新区马运路罗礼科技有限公司研发中心 邮编 215000
E-mail: tigerleihm@yahoo.com.cn 

参考资料:Version Control with Subversion (http://svnbook.red-bean.com/

“本文作者是雷凯 升技主板(苏州)研发中心工程师。他目前在中国苏州 升技主板(苏州)研发中心工作。可以通过tigerleihm@yahoo.com.cn 与他联系。”

 bjchenxu 回复于:2004-12-16 16:33:43
你怎么喜欢用繁体字?

 tigerlei 回复于:2004-12-16 16:35:44
哎,沒有辦法,誰讓我在ABIT這個台資公司啊

 erithe 回复于:2004-12-18 10:03:26
楼主!那你应该是在东莞吧?

 li200 回复于:2004-12-18 11:36:51
与cvs相比它有那些更好的性能?

 tigerlei 回复于:2004-12-20 09:10:00
其實個人目前沒有發現有什么好處,因為CVS用地不是很多.
不過對于CVS每一個文件都有一個版本來說,似乎整齊了很多.

 dualface 回复于:2004-12-21 09:41:14
最大的好处有三个:
1、所有文件都是二进制形式存储,所以不用担心你的图片导入仓库后被破坏。而cvs必须指定-kb参数才行;
2、目录和文件一样具有版本特征,比如test目录在不同的事情也有不同的版本,记录了这个目录的一些属性;
3、仓库中的任何一个项目都可以添加自定义的元数据,例如为你的文件加上一个特别的标记。

至于性能上,虽然subversion在本地处理时慢一点(subversion会比较二进制文件两个版本之间的差异,而cvs只会比较文本文件之间的差异)。不过考虑到通过网络更新一个几十MB大的二进制文件(例如 .psd)时,subversion只传输两个不同的部分(极大的减少了需要传输的数据),所以subversion会比cvs更快完成提交和更新动作。

 飞灰橙 回复于:2004-12-27 13:07:02
俺正在逐步改用svn,
确实比cvs好很多。
svn和相关的工具也在不断的升级中,
所以基本上一两个月就会有更新版。

 双眼皮的猪 回复于:2004-12-27 13:25:14
[quote:1ddd6e07c7="bjchenxu"]你怎么喜欢用繁体字?[/quote:1ddd6e07c7]

文章是好文章,但是字体...
我不喜欢,所以...
abit好公司啊...板子质量顶刮刮...
什么时候tigerlei斑竹给大家发板板,显卡啊,主板啊啥的,呵呵...

 大雪飞扬 回复于:2005-01-03 15:05:42
我按楼主的方法把svn配置svnserver方式后,使用ssh来进行客户验证,

发现我当前root用户在执行
#svn checkout svn+ssh://svn服務器ip/home/mysvn
命令时,系统提示输入了两边确认密码,但是可以成功执行。

在其他用户下执行该命令,在提示输入密码,并且输入完毕后,
报一下错误:

svn: Berkeley DB error while opening environment for filesystem /home/mysvn/db:
Permission denied

为什么呀?

 cx6445 回复于:2005-01-10 13:05:59
[quote:4bf525ede6="dualface"]最大的好处有三个:
1、所有文件都是二进制形式存储,所以不用担心你的图片导入仓库后被破坏。而cvs必须指定-kb参数才行;
2、目录和文件一样具有版本特征,比如test目录在不同的事情也有不同的版本,记录了这个目..........[/quote:4bf525ede6]

我想问一下二进制文件怎么比较文件之间的差异?

 大麻 回复于:2005-01-12 17:51:38
[quote:5f1e9d0a9f="大雪飞扬"]我按楼主的方法把svn配置svnserver方式后,使用ssh来进行客户验证,

发现我当前root用户在执行
#svn checkout svn+ssh://svn服務器ip/home/mysvn
命令时,系统提示输入了两边确认密码,但是可以成功执行。

?.........[/quote:5f1e9d0a9f]

初始化 svn 仓库的时候,要让相应的用户具有读写权限。

 zlhippo 回复于:2005-06-07 14:12:16
svn 里中文文件名是乱码,无法操作,没办法只能操作上级目录(英文),如何解决?

leizhang@corp.netease.com msn:rocklvlei@hotmail.com 欢迎大家交流

原文转自:http://www.ltesting.net