Subversion学习笔记
第1章 基本概念
本章我们学习一下Subversion(简称SVN)的一些基本概念。
- Repository
Repository是指数据的中央存储仓库。Repository以filesystem tree的形式存放信息。若干clinet(客户端)连接到repository并读、写文件,因此SVN是一个典型的client/server架构。
- Lock-Modify-Unlock方案
使用SVN进行版本控制时,我们推荐使用lock-modify-unlock方案,即client端首先对要进行修改的文件加锁,在对文件做修改并提交之后,对文件解锁。其过程如下图所示。
- SVN Repository URL
SVN使用URL来指定repository中的文件和目录。就像下面这样:
svn://svn.example.com/svn_repos/project1
http://128.54.6.72:9800/svn_repos/project2/README
- Working Copy
Working Copy(工作拷贝)是指客户端一侧对repository的镜像。
- Revision
当把客户端的working copy所做的修改集(change set)提交(commit)到repository中时,就会在repository中产生一个filesystem tree的新状态,这个新状态就称为revision。每个revision对应于一个唯一的自然数,这个自然数就是revision number(版本编号)。Revision number适用于整个repository,而不是只适用于单个文件或目录。
- Branch
Branch(分支)是指与其他development line相互独立的一个development line。如下图所示。
每个项目都存在一个开发主线(main line),在SVN中也称为项目的trunk(主分支)。
- Tag
Tag(标记)是一个项目在某个时间点上的“快照”。实际上,一个revision就是一个tag。但是,tag的是主要的作用是保存项目的里程碑状态,并且用一个人们容易阅读的“标记”来标识这个状态。
第2章 Subversion服务器端的管理
2.1 在Ubuntu上配置svnserve
本节介绍如何在Ubuntu 11.04版本上配置svnserve,从而使SVN客户端可以连接到repository。svnserve对于小型开发团队来讲是适合的,因为它的配置比较简单方便。但是svnserve也有缺点,就是svnserve与SVN客户端之间的通信数据是采用明文传输。
1. 安装Subversion。要求安装SVN 1.5以及以上版本。
2. 安装KDiff3。
3. 修改SVN的配置文件/etc/subversion/conf,设置其内容为如下几项:
[helpers]
editor-cmd = gedit
diff-cmd = /etc/subversion/gui_diff.sh
diff3-cmd = /etc/subversion/gui_diff3.sh
[miscellany]
no-unlock = yes
4. 在/etc/subversion/路径下建立shell脚本文件gui_diff.sh,其内容如下。注意将其属性标记为可执行。
#!/bin/sh
kdiff3 "$6" "$7"
5. 在/etc/subversion/路径下建立shell脚本文件gui_diff3.sh,其内容如下。注意将其属性标记为可执行。
#!/bin/sh
TEMP_FILE=`mktemp /tmp/gui_diff3.XXXXXXXXXXXX`
kdiff3 --base "$10" "$11" "$9" --merge --output $TEMP_FILE
cat $TEMP_FILE
rm $TEMP_FILE
exit 0
6. 在Ubuntu的根目录下建立repository,使用的命令如下:
root@jiali-VirtualBox:/# svnadmin create /svn_repos
这时可以看到根目录下多出/svn_repos这个目录。它下面有一些子目录和文件。
root@jiali-VirtualBox:/# ls -al /svn_repos/
total 32
drwxr-xr-x 6 root root 4096 2011-07-10 19:01 .
drwxr-xr-x 24 root root 4096 2011-07-10 19:01 ..
drwxr-xr-x 2 root root 4096 2011-07-10 19:01 conf
drwxr-sr-x 6 root root 4096 2011-07-10 19:01 db
-r--r--r-- 1 root root 2 2011-07-10 19:01 format
drwxr-xr-x 2 root root 4096 2011-07-10 19:01 hooks
drwxr-xr-x 2 root root 4096 2011-07-10 19:01 locks
-rw-r--r-- 1 root root 229 2011-07-10 19:01 README.txt
7. 编辑/svn_repos/conf/svnserve.conf文件,设置svnserve的身份认证和权限设置。编辑的内容主要是[general]这一小节,下面的内容是除了注释之外[general]小节的内容。
[general]
anon-access = none
auth-access = write
password-db = passwd
# authz-db = authz
realm = My Repository
8. 编辑/svn_repos/conf/passwd文件,向其中加入允许连接到repository的客户端的用户名和对应的密码。注意把该文件的权限设置成仅root用户可读可写。
9. 配置svnserve在Ubuntu启动之后自动运行。方法是使用SystemàPreferencesàStartup Applications操作系统菜单项,并加入svnserve条目。其中的Command为svnserve –d –r /svn_repos,如下图所示。
10. 重启Ubuntu。
2.2 Repository的部署策略
在SVN服务器一侧,repository的部署策略一般是:只设置唯一一个repository,并把所有的开发项目都放到该repository下面。比如,在我们所给的示例中,/svn_repos就是SVN服务器侧的唯一的repository。而我们在这个唯一的repository下面希望建立如下图所示的filesystem tree。
/svn_repos
/project1
/trunk
/tags
/branches
/project2
/trunk
/tags
/branches
要在SVN服务器侧建立起如上图的filesystem tree,应该执行如下的命令:
root@jiali-VirtualBox:~# svn mkdir --parents -m "comment" "svn://localhost/project1/trunk"
root@jiali-VirtualBox:~# svn mkdir --parents -m "comment" "svn://localhost/project1/tags"
root@jiali-VirtualBox:~# svn mkdir --parents -m "comment" "svn://localhost/project1/branches"
要在SVN服务器侧观看repository的filesystem tree,应该执行如下的命令:
root@jiali-VirtualBox:~# svn list "svn://localhost"
2.3 Branch管理
软件项目中常见的分支模式有如下两种:
- Feature Branch:传统的桌面应用软件和嵌入式软件项目,通常会大量采用创建分支(branching)和分支合并(merge),其目的是确保trunk分支上的code base尽量稳定、可用。
- Trunk Only:互联网应用软件项目常常仅使用trunk,所有的代码都直接提交到trunk上。这是适应互联网应用本身的特点的:要求快速修复bug并使最新的系统上线运营。为此,Trunk Only的项目也必须配备持续集成和自动化回归测试,以保证新提交的代码所引入构造失败或品质回归问题能尽快得到解决。
在SVN服务器端管理branch的操作我们已经用一个名为svn_branch.sh的shell脚本来封装,它的内容如下。把它拷贝到Linux系统默认的可执行目录/usr/bin下面。
#!/bin/sh
if [ $# != 3 ]; then
echo "usage: svn_branch create|delete|sync_with_trunk|merge_to_trunk project_name branch_name"
fi
command=$1
project_name="$2"
branch_name="$3"
urlPrefix="svn://localhost"
trunk="trunk"
branches="branches"
trunk_url="${urlPrefix}/${project_name}/${trunk}"
branch_url="${urlPrefix}/${project_name}/${branches}/${branch_name}"
if [ $command = "create" ]; then
svn copy "$trunk_url" "$branch_url" --message "Created branch $branch_name"
elif [ $command = "delete" ]; then
svn delete "$branch_url" --message "Deleted branch $branch_name"
elif [ $command = "sync_with_trunk" ]; then
TEMP_DIR=`mktemp -d /tmp/svn_branch.XXXXXXXXXXXX` || exit 1
svn checkout "$branch_url" $TEMP_DIR
svn merge "$trunk_url" $TEMP_DIR
svn commit $TEMP_DIR --message "Synched branch $brach_name with trunk"
rm --force --recursive $TEMP_DIR
rmdir $TEMP_DIR
elif [ $command = "merge_to_trunk" ]; then
TEMP_DIR=`mktemp -d /tmp/svn_branch.XXXXXXXXXXXX` || exit 1
svn checkout "$trunk_url" $TEMP_DIR
svn merge --reintegrate "$branch_url" $TEMP_DIR
svn commit $TEMP_DIR --message "Merged branch $branch_name back to trunk"
svn delete "$branch_url" --message "Deleted branch $branch_name temporarily"
svn copy "$trunk_url" "$branch_url" --message "Recovered branch $branch_name again"
rm --force --recursive $TEMP_DIR
else
echo "unknown command: $command"
fi
要创建一个新的branch,使用命令:
root@jiali-VirtualBox:~# svn_branch create project1 branch_2
要删除一个branch,使用命令:
root@jiali-VirtualBox:~# svn_branch delete project1 branch_2
要让branch与trunk同步,使用命令:
root@jiali-VirtualBox:~# svn_branch sync_with_trunk project1 branch_2
要把branch合并(Merge)回trunk,使用命令:
root@jiali-VirtualBox:~# svn_branch merge_to_trunk project1 branch_2
2.4 Tagging
正如前文所讲,添加标记(Tagging)的目的是当项目进展到某些关键点或里程碑时,保存下项目的“快照”,以方便今后对其回溯。Tagging的命令如下:
root@jiali-VirtualBox:~# svn copy "svn://localhost/project1/trunk" "svn://localhost/project1/tags/tag_1" –m "comment"
第3章 Subversion Ubuntu客户端
3.1 安装流程
1. 安装SVN,要求1.5及其以上版本。
2. 安装KDiff3。
3. 安装RapidSVN,要求能支持SVN 1.5及以上版本。
4. 启动RapidSVN,对其进行如下的设置。
3.2 使用策略
使用RapidSVN来进行Lock,Check Out,Commit,Diff,Revert等操作都是非常直观的,因此我们在这里不做讲述。我们只是重点强调一下,在对需要的文件进行修改之前,一定使用Lock操作把该文件加锁!