Chinaunix首页 | 论坛 | 博客
  • 博客访问: 87830
  • 博文数量: 44
  • 博客积分: 2525
  • 博客等级: 少校
  • 技术积分: 316
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-25 17:01
文章分类

全部博文(44)

文章存档

2010年(44)

我的朋友

分类: LINUX

2010-06-23 16:31:18

安装环境:
OS: RedHat Linux 9
需要软件,google很容易搜索到:
SVN: Subversion 1.5.1
HTTPD: Apache Httpd 2.2.9
APR: Apache Apr 1.3.3
APU: Apache Apr-Util 1.3.4
1. 下载源代码:
到各自的官方网站下载相应的源代码的tar.bz2包,解包后准备编译安装:
2. 编译源代码:
按下面的顺序编译源代码:
(1) Apache Apr
# tar jxvf apr-1.3.3.tar.bz2
# cd apr-1.3.3
# ./configure --prefix=/usr/local/apr
# make
# make install
(2) Apache Apr-Util
# tar jxvf apr-util-1.3.4.tar.bz2
# cd apr-util-1.3.4
# ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr
# make
# make install
(3) Apache Httpd
# tar jxvf httpd-2.2.9.tar.bz2
# cd httpd-2.2.9
# ./configure --prefix=/usr/local/apache2 --enable-dav --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util
# make
# make install
(4) Subversion
# tar jxvf subversion-1.5.1.tar.bz2
# cd subversion-1.5.1
# ./configure --prefix=/usr/local/subversion --with-apxs=/usr/local/apache2/bin/apxs  --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util
# make
# make install
以上的编译通常情况都能顺利编译成功,得到相应的可执行程序。
检查WebDav for SVN 模块:
# cd /usr/local/apache2/modules
检查 mod_dav_svn.so 和 mod_authz_svn.so,如果上述第2步编译成功,这两个模块应该可以看到。
3. 创建svn用户:
# groupadd svn
# useradd -g svn svn
# passwd svn
以后代码库的创建维护等,都用这个帐户来操作。
4. 创建版本库:
以svn用户登录
准备环境变量:
$ SVN_HOME=/usr/local/subversion
$ export SVN_HOME
$ PATH=$PATH:$SVN_HOME/bin
$ export PATH
上述命令创建了版本库sandbox,用于测试:
$ svnadmin create --fs-type fsfs sandbox
还可以再创建工程的版本库:
$ svnadmin create --fs-type fsfs projects
创建启动Subversion的脚本:
$ echo '/usr/local/subversion/bin/svnserve -d -r /home/svn/' > startup.sh
$ chmod +x startup.sh
$ ./startup.sh
将启动脚本放置到开机自动启动脚本中:
以root身份修改文件:/etc/rc.d/rc.local,添加以下文字:
su -c /home/svn/startup.sh svn
5. 配置Apache Httpd
# cd /usr/local/apache2/conf
# vi httpd.conf
加载WebDav for SVN模块:
#
# Dynamic Shared Object (DSO) Support
#
# To be able to use the functionality of a module which was built as a DSO you
# have to place corresponding `LoadModule' lines at this location so the
# directives contained in it are actually available _before_ they are used.
# Statically compiled modules (those listed by `httpd -l') do not need
# to be loaded here.
#
# Example:
# LoadModule foo_module modules/mod_foo.so
LoadModule dav_svn_module     modules/mod_dav_svn.so
LoadModule authz_svn_module   modules/mod_authz_svn.so
添加最后两行(默认编译后,configure会自动加上):
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so

修改启动httpd的默认用户:
#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch. 
#
# User/Group: The name (or #number) of the user/group to run httpd as.
# It is usually good practice to create a dedicated user and group for
# running httpd, as with most system services.
#
#User daemon
#Group daemon
User svn
Group svn
将执行httpd的用户和组设为svn,这样做是为了让httpd进程能访问版本库的数据。

在Apache Http Server里配置虚拟主机:
将httpd.conf中的虚拟主机的注释去掉,然后编辑/usr /local/apache2/conf/extra/httpd-vhost.conf。

# Virtual hosts
Include conf/extra/httpd-vhosts.conf
添加虚拟主机svn.yourcompany.com,当然,这个主机名需要使用你自己的域名。
# vi /usr/local/apache2/conf/extra/httpd-vhost.conf


    ServerAdmin
    ServerName svn.yourcompany.com
    ErrorLog logs/svn.yourcompany.com-error_log
    CustomLog logs/svn.yourcompany.com-access_log common
   
       DAV svn
       SVNListParentPath on
       SVNParentPath /home/svn
   


 
 这样配置的目的是可以使用 或 这样的URL来供各种客户端通过http协议访问该版本库中的文件。
6. 用户认证和授权
用户认证是为了验证访问SVN的用户身份,授权是为了约束用户的权限,约束用户读写每个目录或文件的权限,请参阅 SVN相关的文档。通过http协议的认证和通过svn协议的认证略
有不同,需要注意。

SVN 管理:
这一部分主要是指管理repository,使用svnadmin等。
首先使用svn登录系统。下面的操作都在 svn的主目录里进行。
1. 使用
$ svnadmin help
$ svnserve help
可以查看 svnadmin和svnserve的帮助信息。
2. 创建repository
2.1 可以把所有的项目都放在一个repos里,
/path/to/repos/ProjectA,
/path/to/repos/ProjectB
然 后每个项目下再建立各自的trunk,branch,tag(这三个东西的含义参考svn-book:Chapter4:Branching and Merging,或者继续阅读下面的branch部分知道一个基本的意思)。这样的好处是对于svn使用时帐号的管理及其他一些hooks(此概念参考 svn-book:Chapter5:Repository Administration: Repository Creation and Configuration:Hook Scrips)等可以共享,管理起来只需一次,代价是灵活性可能不够或者达到某种灵活性需要复杂配置。
也 可以每个项目建立独立的repos
/path/to/ProjectArepos
/path/to/ProjectBrepos
当 然每个下面也建自己的trunk,branch,tag等。这种设置的好处显然就是有足够的灵活性,但是管理工作就多一些,特别是当有几个项目的设置相同 时,修改了一个,就要修改其他的。
现在我的习惯是第二种,即每个项目有自己的repos,因为只是个人的简单的使用,做完一个算一个。
2.2 使用
$ svnadmin create /path/to/repos
默认创建的是FSFS型的repos,还有 BerkerleyDB型的,使用–fs-type来指定类型。
$ svnadmin create –fs-type fsfs /path/to/repos
$ svnadmin create –fs-type bdb /path/to/repos
关于 FSFS和BerkerleyDB的内容参考svn-book:Chapter5:Repository Administration: Repository Basics:Repository Data Stores。看起来FSFS更好一些,而且Windows下好像FSFS麻烦更少。
现在假设项目名称叫MIS,建立repos如下:
$ svnadmin create –fs-type fsfs /home/svn/mis
这样svnadmin就生成了mis目录,其下还有 许多辅助目录。这些目录的说明可以在svn-book:Chapter5:Repository Administration: Repository Creation and Configuration下找到。
其中/home/svn/mis/conf是这个repos的配置文件存放的地 方,/home/svn/mis/hooks是hooks脚本的存放位置。
3 启动svnserve。使用
$ svnserve -d -r /home/svn
来启动svnserve。其中-d参数是让svnserve以deamon模式运行在后台,-r参数使得客户端只能访问 到后面指定的目录以下的内容(这里是/home/svn下的内容)。
4 设置访问用户名和口令
/home/svn/mis/conf里是 mis这个repos的配置文件,svnserve.conf是主配置文件,默认的里面有(记得打开[general]前的注释,并且让 [general]位于行首)
[general]
anon-access = read
auth-access = write
password-db = passwd

文档有良好的注释
这里将anon-access的访问权限从read改为none,然后就可以在 passwd(password-db指定的,这里位置为/home/svn/mis/conf/passwd)里配置帐号和口令了。
在 /home/svn/mis/conf/passwd里[user]下加入下面一行
deller = dellerpwd
这样就可以用 deller:dellerpwd来访问了。
关于配置文件的更多信息,可以参考
$ man svnserve.conf,
google 可以查到此页的翻译(目前在)
还 有svn-book:Chapter7 Advanced Topics:Runtime Configuration Area:Configuration Options
5. 项目中repos布局
根据实践经验,一个项目的生存周期也不是单线的,常常 有一些分支(分支剧情?)或者稳定版发布或者特定功能的实验性加入等事件,repos的布局需要进行一定设计来支持这些“事件”。常见的布局是这样的
Project/trunk
Project/branches
Project/tags
trunk 是项目主体存放位置
branches是项目的各种分支的存放
tag往往用于公开发布的版本的存档,类似与milestone。
(trunk,branch,tag 这三个东西的含义参考svn-book:Chapter4:Branching and Merging)
建立这样的布局的方法有许多,svn- book上说可以用svn mkdir等命令逐一建立,然后提交。还有一个比较便捷的方法如下(使用svn import):
$ mkdir tmpdir
$ cd tmpdir
$ mkdir trunk
$ mkdir branches
$ mkdir tags

$ svn import . –message ‘Initial repository layout’
说明:
a. 这里仍然是按照前面的一个项目一个repos来做的,如果是多个项目共用一个repos时,就要在tmpdir下先建立这些项目,再在其下建立各自的 trunk等
b. 注意最后的svn import一句中的file://这是不可少的,因为这个操作是在repos的服务器端,这样做Initial repository import时,可能svnserve没有启动,但是由于svn支持本地直接访问,所以可以完成,而这时,就是通过“file://”来告诉svn目前是 在操作本地repos的,比如linux下,/home/svn/mis为一个repos,那么应该写为“file:///home/svn/mis”
6. repos的删除,注意不是清空。可能有svnadmin的命令吧,但其实只要删掉repos的目录就完全删除了,比如
$ rm -rf /home/svn/mis
7. 更多的管理功能包括:repos的查看(svnlook),repos的清除、恢复、备份、迁移(svnadmin)等主题,可以参考svn- book:Chapter5 Repository Administration
SVN使用:
1. 首先是安装TortoiseSVN这个Win下的客户端(当然用subversion自己的svn这个客户端也可以完成所有操作,理论上)。这个客户端是 集成到Explore里的,所以没有什么独立的窗体,所有操作右键菜单来完成。
2. svn使用基本流程:
下面说的命令都与 TortoiseSVN菜单上的名称一致。
a. 初次(initial)取出(checkout)repos,建立本地工作拷贝(WC WorkingCopy)。
b. 与repos同步(update),保证将要进行的编辑是最新版本。
c. 编辑源代码(包括创建、修改、删除)。
d. 与repos同步(update),提交之前先要同步到最新的版本,保证所有在自己之前的有关提交已经在本地有所知晓。
e. 解决冲突(resolve conflict)。
f. 提交(commit),一定要写上这次提交的内容的摘要,便于以后查阅。
g. 继续b。
每次开始新的编辑前的同步repos很重要,另外经常地update没有坏处,特别是多人项目中。如果每次提交(commit)前不进行 更新(update)的到最新的版本的话,svn会提示当前的拷贝过期,需要更新。
在使用的过程中,时刻注意当前的工作拷贝(WC WorkingCopy)所对应的URL很重要,特别是当有了branches和tag等时候。使用svn info可以查看到这些信息。使用TortoiseSVN时,通过下面的操作查看这些信息:右键单击工作拷贝的根文件夹(不是上级文件夹),菜单中选择则 属性(不是TortoiseSVN那个菜单),然后在出现的对话框中选择Subversion标签就可以看到了。
3. 使用branches
(关 于branches的内容可以在svn-book:Chapter4 Branching and Merging得到)
当多个人合作 (Sally和John)时,可能有这样的情况出现:John突然有个想法,跟原先的设计不太一致,可能是功能的添加或者日志格式的改进等等,总而言之, 这个想法可能需要花一段时间来完成,而这个过程中,John的一些操作可能会影响Sally的工作,John从现有的状态单独出一个project的话, 又不能及时得到Sally对已有代码做的修正,而且独立出来的话,John的尝试成功时,跟原来的合并也存在困难。这时最好的实践方法是使用 branches。John建立一个自己的branch,然后在里面实验,必要的时候从Sally的trunk里取得更新,或者将自己的阶段成果汇集到 trunk中。
附:TortoiseSVN帮助里的branch的说明:
One of the features of version control systems is the ability to isolate changes onto a separate line of development. This line is known as a branch. Branches are often used to try out new features without disturbing the main line of development with compiler errors and bugs. As soon as the new feature is stable enough then the development branch is merged back into the main branch (trunk).
3.1 创建branch
(详细的解释参考svn-book:Chapter4 Branching and Merging:Using Branches:Creating a Branch)
实际是svn copy操作
$ svn copy SourceURL/trunk \
       DestinationURL/branchName \
      -m “Creating a private branch of xxxx/trunk.”
TorToiseSVN操作更为简单,只要在 working copy里右键空白,然后在TorToiseSVN菜单中选择Branches/Tags,就可将整个目录分支(branch)出去,或者点击某个文件将 文件单独分支(branch),而且有多种选择,指定是“直接在服务器端copy HEAD版本”、“直接在服务器端copy指定版本”(这两种相当于svn copy中源和目的都是URL)、“用当前的工作拷贝(WC Working Copy)生成”。同时还有一个checkbox用于在完成了这次分支(branch)后直接切换(switch)当前的工作拷贝(WC Working Copy)到分支。
3.2 使用merge来应用branch的修改
3.2.1 trunk的变化及时更新到branch
例子原型出自svn-book:Chapter 4:Branching and Merging:Copying Changes Between Branches:Copying Specific Changes
接着前 面的例子,John在实验过程中,Sally对原有的某个文件做了一些改动,如拼写检查等,John知道了,希望将这些改动也放到自己的当前的工作拷贝 (WC Working Copy)中。svn中使用merge指令来完成。假设Sally的修订使repos从Rev345到了Rev346,所以John就是要将 Rev345:Rev346(前:后)的变更应用到当前的WC。使用TortoiseSVN的操作就是在WC中右键空白处,然后在相关菜单中选择 “Merge…”,在弹出的对话框中,From指定比较前项的位置和版本(这里是trunk的Rev345),To指定后项的位置和版本(这里是 trunk的Rev346,可以使用一个复选框使的To的位置与From相同)。
相应的svn merge指令参考后面“merge操作实质”可知。
3.2.2 branch最终合并回trunk
例子原型出自svn- book:Chapter 4:Branching and Merging:Common Use-Cases:Merging a Whole Branch to Another
John经过尝试,终于实现了想法,并通过测试,现在他决定将所有的工作合并到trunk去。
这里要 注意的是,John打算合并的是自己的工作,假设John的branch(johnBranch)开始于Rev233,John的工作提交到repos是 Rev289,那么John的工作是将johnBranch:Rev233到johnBranch:Rev289的内容合并到trunk。而不是 johnBranch:Rev233到trunk:HEAD,因为这个变化包含了对John工作的增加和对trunk中其他人的工作的撤销(如果John 没有及时将他人在trunk的工作合并到自己的johnBranch的话)。
TortoiseSVN的操作是这样的,先checkout出 trunk(也可以switch到trunk),即保证当前的工作拷贝(WC WorkingCopy)是trunk,然后使用菜单中的“Merge…”,选择From为johnBranch:Rev233选择To为 johnBranch:Rev289。
相应的svn merge指令参考后面“merge操作实质”可知。
3.2.3 merge操作的实质
svn merge命令的原型如下
svn merge sourceURL1[@N] sourceURL2[@M] [WCPATH]
svn merge [WCPATH]
svn merge -r N:M SOURCE[@REV] [WCPATH]
In the first and second forms, the source paths (URLs in the first form, working copy paths in the second) are specified at revisions N and M. These are the two sources to be compared. The revisions default to HEAD if omitted.
In the third form, SOURCE can be a URL or working copy item, in which case the corresponding URL is used. This URL, at revisions N and M, defines the two sources to be compared.
WCPATH is the working copy path that will receive the changes. If WCPATH is omitted, a default value of “.” is assumed, unless the sources have identical basenames that match a file within “.”: in which case, the differences will be applied to that file.
可 以看出merge实际是比较前后(源:目的)两个版本(revision)之间的差别(用运算符就是 目的 – 源),然后将这些差别应用(施用)到工作拷贝(WC WorkingCopy)上的一个操作,根据源与目的版本号的先后,出现了“合并”、“撤销”(源版本号大于目的版本号)等不同效果,然后通过提交 (commit)来将这些效果保存到服务器端的repos中。
4. 版本(Revision)关键字
HEAD, BASE, COMMITTED, PREV是指定版本号时可以使用的一些保留字,含义如下:(参考svn-book:Chapter3:Guided Tour:Revisions:Numbers,Keywords)
HEAD:The latest revision in the repository.
BASE:The “pristine” revision of an item in a working copy.
COMMITTED:The last revision in which an item changed before (or at) BASE.
PREV:The revision just before the last revision in which an item changed. (Technically, COMMITTED - 1.)
说明:
a. 只有HEAD能用于URL,BASE,COMMITTED,PREV都是用于工作拷贝(WC Working Copy)的。
b. HEAD虽然含义是“当前最新的版本”,但用于WC时,当前未提交(即未进入版本管理)的变化是不包含在内的。所以比如:
刚commit过 main.txt为Rev10,即HEAD=10,COMMITTED=10,这时对main.txt进行一些编辑,然后svn diff -r HEAD:COMMITTED,不会显示刚刚的编辑操作,因为刚刚的编辑操作并没有纳入到版本管理,即HEAD没有反映出“当前最新”,实际是反映的“当 前版本管理中的最新”。
c. BASE的含义,上面的英文说得不够清楚,其实是指最后一次更新(update)操作 或者 取出(checkout)操作(当initial checkout)时取出的那些文件,这些被svn无修改地保留在.svn管理目录里。
5. 文件的添加、删除、重命名
当向项目里添加了一个新文件时,需要使用TortoiseSVN菜单中的“add”指令来为下一次commit做添加文 件的准备,使得下次commit时知道有这样的事件发生。对应的svn命令行操作就是svn add。
当从项目里删除文件时,也需要显示地将这个 事件告诉svn,方法就是右键单击要删除的文件,在TortoiseSVN菜单中选择删除,而不是简单地用os的删除。
文件重命名与删除同理。
6. 忽略列表
比如一个VC的项目用subversion管理,vc会生成debug目录,release目录以及其下的编译临时文件,而我们可能只 需要对源文件进行版本管理,那些临时文件都不关心,这时可以把他们加入ignore list。同样使用TortoiseSVN菜单完成这个。对于错误的加入到了ignore list的文件,可以在TortoiseSVN菜单中的Remove from ignore list撤销。这个暂时不知道svn对应的命令。
7. 解决冲突(conflict)
所谓冲突,简单地说,就是两个人改了同一个地方,而修改又不同。比如Sally和John同时Update到了最 新的trunk,Rev5。Sally吧main.txt的第一行改为了x=5,提交了,然后repos到了Rev6,同时John在自己的工作拷贝 (WC WorkingCopy)中,把main.txt第一行改成了x=6,然后准备同步(update)repos然后提交,可是在update的时候就会提 示出现了冲突(conflict)。这时svn目录下出现了几个文件:main.txt.mine, main.txt.r5, main.txt.r6
按 照svn-book的解释,含义如下:
filename.mine : This is your file as it existed in your working copy before you updated your working copy—that is, without conflict markers. This file has your latest changes in it and nothing else. (If Subversion considers the file to be unmergeable, then the .mine file isn’t created, since it would be identical to the working file.)
filename.rOLDREV : This is the file that was the BASE revision before you updated your working copy. That is, the file that you checked out before you made your latest edits.
filename.rNEWREV : This is the file that your Subversion client just received from the server when you updated your working copy. This file corresponds to the HEAD revision of the repository.
其实就是main.txt.mine是John执行update之前的本地文 件main.txt,main.txt.r5是本地上次update时得到的,即BASE版,而main.txt.r6是这次update得到的。这时还 有一个main.txt文件其实是包含了相互冲突的内容的用于手工解决冲突的文件。
解决冲突有三个方法:
a. 手工解决。编辑main.txt,保存其成为最终希望的版本。然后使用svn resolved去掉conflict标志。TortoiseSVN的操作这次要复杂一些,在main.txt上右键,菜单中选择 “resolved…”,在弹出的对话框中右键main.txt,然后在对话框中选择“resolved”,tortoiseSVN会要求确认一次,选择 yes之后会发现生成的三个临时文件没有了,而main.txt的冲突标记变成了修改。
b. 直接选用使用一个临时文件。命令行相当于这样:
$ cp main.txt.mine main.txt
然后同样要用svn resolved去掉conflict标志。这个方法的TortoiseSVN的操作是在“resolved”对话框里,右键main.txt的菜单上选 择“Resolved conflict using mine”或者“Resolved conflict using theirs”
c. 撤销更改。这是John决定放弃自己对main.txt的更改并且接受Rev6版时的做法。用这种方法,如果是用svn这个client时,无需调用 svn resolved了,因为不打算提交新的内容到repos(当然如果其他的resolve决定提交新的内容时,还要对其他文件resolved的)。 TortoiseSVN里的操作是在冲突菜单(resolved对话框里右键单击要解决冲突的文件时出现的菜单)里选择Revert,同样 tortoise会让要求确认一次。
当有多个conflict时,需要一个一个resolve,TortoiseSVN的Resolved对话框 里每次都是对一个对象进行操作,尽管前面的有复选框(复选框作用未知,猜测是跟lock有关)。


阅读(899) | 评论(0) | 转发(0) |
0

上一篇:oprofile

下一篇:Embedded Linux FAQ, Help & Docs

给主人留下些什么吧!~~