[toc]

0x00 快速入门

什么是SVN?
答:Apache Subversion 通常被缩写成 SVN,是一个开源的中心服务器版本控制系統,Subversion 在 2000 年由 CollabNet Inc 开发,现在发展成为 Apache 软件基金会的一个项目,同样是一个丰富的开发者和用户社区的一部分(现在基本已经被git取代);

为什么要使用SVN?
答:程序员在编写程序的过程中,每个程序员都会生成很多不同的版本,这就需要程序员有效的管理代码,在需要的时候可以迅速,准确取出相应的版本。而这些数据是放置在一个中央资料档案库(repository) 中,这个档案库很像一个普通的文件服务器, 不过它会记住每一次文件的变动;这样您才能把档案恢复到旧的版本, 或是浏览文件的变动历史。

SVN 术语:

  • repository(源代码库):源代码统一存放的地方
  • Checkout(提取):当你手上没有源代码的时候,你需要从repository checkout一份
  • Commit(提交):当你已经修改了代码,你就需要Commit到repository
  • Update (更新):从中央服务器中拉取最新的代码到本地;

SVN 的主要功能:

  • (1)目录版本控制
  • (2)真实的版本历史
  • (3)自动提交
  • (4)纳入版本控管的元数据
  • (5)选择不同的网络层
  • (6)一致的数据处理方式
  • (7)有效的分支(branch)与标签(tag)
  • (8)Hackability


SVN 生命周期

  • 1.创建版本库:版本库相当于一个集中的空间,用于存放开发者所有的工作成果,采用Create 操作是用来创建一个新的版本库;
  • 2.检出:Checkout 操作是用来从版本库创建一个工作副本(开发者私人的工作空间)。
  • 3.更新:Update 操作是用来更新版本库的使工作副本与版本库进行同步。
  • 4.执行变更:
    • commit 操作后将被添加进待变更列表中文件提交到版本库中。
    • Rename 操作可以更改文件/目录的名字使之版本库也会相对应的更改。
  • 5.复查变化:
    • Status 操作只是提供了一个变动列表,但并不提供变动的详细信息。
    • diff 操作来查看这些变动的详细信息。
  • 6.修复错误:revert 操作重置了对工作副本的修改。它可以重置一个或多个文件/目录
  • 7.解决冲突:合并的时候可能会发生冲突;
    • Merge 操作会自动处理可以安全合并的东西;
    • Resolve 操作就是用来帮助用户找出冲突并告诉版本库如何处理这些冲突。
  • 8.提交更改:Commit 操作是用来将更改从工作副本到版本库,并且Commit 是一个原子操作,也就是说要么完全提交成功,要么失败回滚。


问:搭建SVN服务常用什么工具?
答:Subversion

Subversion是什么?
它是一个自由/开源的版本控制系统,一组文件存放在中心版本库,记录每一次文件和目录的修改,Subversion允许把数据恢复到早期版本,或是检查数据修改的历史,Subversion可以通过网络访问它的版本库,从而使用户在不同的电脑上进行操作。

TortoiseSVN图标介绍

  • 一个新检出的工作复本使用绿色的对勾重载,表示Subversion状态正常
  • 在你开始编辑一个文件之后,状态就变成了已修改,而图标重载已变成了红色感叹号。通过这种方式,你可以很容易地看出那些文件从你上次更新工作复本被修改过且需要提交
  • 如果在提交的过程中出现了冲突,图标就会变成了黄色感叹号
  • 加号告诉你有一个文件或者目录已经被计划加入到版本控制中
WeiyiGeek.图标介绍

WeiyiGeek.图标介绍

注意事项:

  • .svn这个隐藏目录记录着两项关键信息:工作文件的基准版本和一个本地副本最后更新的时间戳,千万不要手动修改或者删除这个.svn隐藏目录和里面的文件!!,否则将会导致你本地的工作拷贝(静态试图)被破坏,无法再进行操作。

0x01 SVN服务搭建

描述:SVN Server即可以在Windows上也可以在Linux中进行安装使用;

1
2
yum install -y subversion
apt-get install subversion

而我们下面实验是以Windows Server 2008R2环境为主,考虑到只是一些老项目在使用svn而现在大部分的开发也以及采用git进代码管理;

搭建实例

  1. 首先来下载和搭建SVN服务器,下载地址如下: http://subversion.apache.org/packages.html (根据的系统位数和操作系统下载可以自己选择)
    个人认为最好用VisualSVN server 服务端和 TortoiseSVN客户端搭配使用,下载地址:https://www.visualsvn.com/downloads/
WeiyiGeek.VisualSVN server

WeiyiGeek.VisualSVN server

  1. VisualSVN server服务端的安装与配置(基本下一步)
  • 安装选项 VisualSVN Server and Management Console
  • 标准安装还是专业安装自己根据需求选择
  1. 点击【Finish】即可完成安装。安装完成后,启动VisualSVN Server Manager,如图:
    窗口的右边看到版本库的一些信息,比如状态,日志,用户认证,版本库等.
    WeiyiGeek.SVN

    WeiyiGeek.SVN


  1. TortoiseSVN 客服端的安装,需要下载两个一个语言包一个程序安装包,点开上面的TortoiseSVNSVN连接,下载TortoiseSVNserver,下载完成后双击安装如下图:
WeiyiGeek.安装客户端

WeiyiGeek.安装客户端

  1. 安装完成后,在我右键就可以看到TortoiseSVN;说明snv已经安装成功了!安装语言包直接打开下一步即可

0x02 基础使用

VisualSVN server

  1. 要建立版本库,需要右键单击左边窗口的Repositores,如下图:在弹出的右键菜单中选择Create New Repository或者新建->Repository:

    WeiyiGeek.新建仓库

    WeiyiGeek.新建仓库

  2. 设置建立的仓库权限:All Subcersion users have read / write access,点击【Finish】即可完成基本创建。


VisualSVN Client

  1. checkout项目文件:新建或者进入目录下(比如qianduan1),右键 –> Svn Checkout –> 并且在先在代码浏览器里简历File;

    WeiyiGeek.

    WeiyiGeek.

  2. 将复制的版本库URL粘贴上,点击【ok】按钮后就可以检索出来,如下:

    WeiyiGeek.

    WeiyiGeek.

  3. 项目结构
    建项目结构:E:\Repositories\WeiRepository\TestProject,在Project里面建立.trunk、tags、branches三个目录

  • 初始项目就放在trunk主干文件夹里(相当于你真正的项目代码在trunk文件夹里),当trunk里可以发布第一个版本时,就用SVN创建分支,先放一份在branches/version/里;

  • 然后可以把branches/version/里打个包放在tags里,然后继续在主干里开发后面的版本如果之前发布的版本有BUG,就直接在branches/version/里创建修订版本,还是放在branches/version(new)/;

  • tags里面只放置各版本,但不进行修改,branches里放发布版,及发布版对应的修订版,以版本号为子文件夹名,甚至还可以将修订版与trunk里合并;

4.复制档案及目录 branch

  • 比如:有另外一个复制的目录来进行新的编修,等到确定这个分支的修改已经完毕了,再合并到原来的主要开发版本,这时我只需要为 trunk 这个目录建立一个 branch。
WeiyiGeek.

WeiyiGeek.

5.合并动作 merge

  • 假如我们在 branch 分支中对文件进行了修改或增加了文件,要 merge 回 trunk 目录中,方法很简单。以上面的例子来说,我们在 D:\Secruity\trunk目录空白处,按下鼠标右键,选择 Merge(合并):

  • 前面的 From: 与 To: 是要问您打算从 Branch 中的哪个版本到哪个版本,merge 回原来的 trunk 目录中。因此,From 跟 To 的 URL 字段应当都是指定原来 branch 的目录下。

WeiyiGeek.

WeiyiGeek.

6.制作 Tag 或是 Release

  • 所谓的 Tag 或是 Release 就是一个特别的版本,因为这个版本可能有特别的意义。其实 Tag 与 Release 的作法与 Branch 完全相同。只是 Branch 可能会需要 merge 回原来的 trunk 中,而 tag 及 release 大部分都不需要 merge 回 trunk 中。
  • 成功的话,您就在对应的 Tag 目录下面建立了一个 v1.0 的目录。当然,如果您这时到 Tag 的目录下面去,会看不到这个目录,您需要在 Tag 目录下面 update 一下,才能看到它。
WeiyiGeek.

WeiyiGeek.


0x03 命令操作

1.SVN Server

(1)版本库创建
主要针对于在服务端进行SVN版本库的相关配置:

1
2
3
4
5
6
7
mkdir /opt/svn

#利用svn命令创建版本库
svnadmin create /opt/svn/runoob

#使用命令svnserve启动服务
svnserve -d -r 目录 --listen-port 端口号

由于-r 配置方式的不一样,SVN启动就可以有两种不同的访问方式:

1
2
3
4
5
6
7
8
9
10
#方式一:-r直接指定到版本库(称之为单库svnserve方式)
svnserve -d -r /opt/svn/runoob #个svnserve只能为一个版本库工作。使用类似这样的URL:svn://192.168.0.1/ 即可访问runoob版本库

#authz配置文件
[groups]
admin=user1
dev=user2
[/]
@admin=rw
user2=r

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#方式二:指定到版本库的上级目录(称之为多库svnserve方式-常用)
svnserve -d -r /opt/svn #一个svnserve可以为多个版本库工作,使用类似这样的URL:svn://192.168.0.1/runoob 即可访问runoob版本库。

#authz配置文件
[groups]
admin=user1
dev=user2
[runoob:/]
@admin=rw
user2=r

[Secruity:/]
@admin=rw
user2=r


(2) 用户和权限
描述:进入/opt/svn/Secruity/conf目录修改默认配置文件配置,包括svnserve.conf、passwd、authz配置相关用户和权限。
svn服务配置文件为版本库目录中的文件conf/svnserve.conf

1
2
3
4
5
6
[general]
anon-access = none
auth-access = write
password-db = /home/svn/passwd
authz-db = /home/svn/authz
realm = tiku

  • anon-access: 控制非鉴权用户访问版本库的权限,取值范围为”write”、”read”和”none”。 即”write”为可读可写,”read”为只读,”none”表示无访问权限。 默认值:read

  • auth-access: 控制鉴权用户访问版本库的权限。取值范围为”write”、”read”和”none”。 即”write”为可读可写,”read”为只读,”none”表示无访问权限。 默认值:write

  • authz-db: 指定权限配置文件名,通过该文件可以实现以路径为基础的访问控制。 除非指定绝对路径,否则文件位置为相对conf目录的相对路径。 默认值:authz

  • realm: 指定版本库的认证域,即在登录时提示的认证域名称。若两个版本库的 认证域相同,建议使用相同的用户名口令数据文件。 默认值:一个UUID(Universal Unique IDentifier,全局唯一标示)。


用户名口令文件passwd:由svnserve.conf的配置项password-db指定;

1
2
3
[users]
admin = admin
thinker = 123456


权限配置文件:由svnserve.conf的配置项authz-db指定,默认为conf目录中的authz

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#[groups]配置段中配置行格式如下:
<用户组> = <用户列表>

#版本库路径权限段的段名格式如下:
[<版本库名>:<路径>]

#基础性示例
[groups]
g_admin = admin,thinker

[admintools:/]
@g_admin = rw
* =

[test:/home/thinker]
thinker = rw
* = r


2.Client Server

(1)SVN 检出操作

1
$svn checkout svn://192.168.0.1/Secruity --username=user01


(2)SVN 提交操作

1
2
3
4
5
6
7
8
9
10
11
12
#查看工作副本中的状态。
svn status

#将文件readme加到版本控制,等待提交到版本库。
svn add readme

#此时 readme的状态为A,它意味着这个文件已经被成功地添加到了版本控制中。
$svn status
A readme

#上注释信息来提交
svn commit -m "SVN readme."


(3)SVN 解决冲突
版本冲突原因:
假设 A、B 两个用户都在版本号为 100 的时候,更新了 kingtuns.txt 这个文件,A 用户在修改完成之后提交 kingtuns.txt 到服务器, 这个时候提交成功,这个时候 kingtuns.txt 文件的版本号已经变成 101 了。
同时B用户在版本号为 100 的 kingtuns.txt 文件上作修改, 修改完成之后提交到服务器时,由于不是在当前最新的 101 版本上作的修改,所以导致提交失败。

现版本冲突的解决方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#查看更改
svn diff

#提交更改
svn commit -m "change HelloWorld.html first"

#此时提交失败,为了避免两人的代码被互相覆盖,Subversion 不允许我们进行这样的操作。
#所以我们在提交更改之前必须先更新工作副本。所以使用 update 命令
svn update #输入"mc",以本地的文件为主。你也可以使用其选项对冲突的文件进行不同的操作
# 选择:(p)推迟,(DF)显示DIFF,(E)编辑文件,(M)合并,
# (MC)我冲突的一面,(TC),其冲突的一面,
# (s)显示全部选项:MC

#默认是更新到最新的版本(可以指定更新)
svn update -r6

#此时工作副本是和仓库已经同步,可以安全地提交更改了
svn commit -m "change HelloWorld.html second"


(4)SVN 版本回退
描述:svn revert 操作将撤销任何文件或目录里的局部更改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
svn status
#通过 svn revert 文件 readme 回归到未修改状态。
svn revert readme

#进行 revert 操作之后,readme 文件恢复了原始的状态
svn status

#revert 操作不单单可以使单个文件恢复原状, 而且可以使整个目录恢复原状。恢复目录用 -R 命令
svn revert -R trunk

#假如我们想恢复一个已经提交的版本怎么办为了消除一个旧版本,我们必须撤销旧版本里的所有更改然后提交一个新版本( reverse merge)

#首先,找到仓库的当前版本,现在是版本 22,我们要撤销回之前的版本,比如版本 21。
svn merge -r 22:21 readme


(5)SVN 查看历史信息
描述:通过svn命令可以根据时间或修订号去除过去的版本,或者某一版本所做的具体的修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#svn log: 用来展示svn 的版本作者、日期、路径等等。
svn log -r 6:8 #查看特定的某两个版本之间的信息
svn log trunk/HelloWorld.html #查看某一个文件的版本修改信息
svn log -l N -v #目录的信息以及显示限定N条记录的目录信息


#svn diff: 用来显示特定修改的行级详细信息。哺乳纲不带任何它将会比较你的工作文件与缓存在 .svn 的"原始"拷贝。
svn diff -r 3 rule.txt #比较你的工作拷贝(本地)和版本库中版本号为 3 的文件 rule.txt
svn diff -r 2:3 rule.txt #较版本库与版本库


#svn cat: 取得在特定版本的某文件显示在当前屏幕。
svn cat -r 版本号 rule.txt

#svn list: 显示一个目录或某一版本存在的文件(可以在不下载文件到本地目录的情况下来察看目录中的文件)。
svn list http://192.168.0.1/Secruity


(6)SVN分支(重点)
比如项目 demo 下有两个小组,svn 下有一个 trunk 版。

  • 由于客户需求突然变化,导致项目需要做较大改动,此时项目组决定由小组 1 继续完成原来正进行到一半的工作(某个模块),小组 2 进行新需求的开发。
  • 那么此时我们就可以为小组2建立一个分支,分支其实就是 trunk 版(主干线)的一个copy版,不过分支也是具有版本控制功能的,而且是和主干线相互独立的,当然,到最后我们可以通过(合并)功能,将分支合并到 trunk 上来,从而最后合并为一个项目。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#1.我们在本地副本中创建一个 my_branch 分支。
svn copy trunk/ branches/my_branch
svn status

#2.提交新增的分支到版本库。
svn commit -m "add my_branch"

#3.接着我们就到 my_branch 分支进行开发,切换到分支路径并创建 index.html 文件并将其将加入版本控制,并提交到版本库中。
~/svn/Secruity/branches/my_branch# svn status
? index.html
~/svn/Secruity/branches/my_branch# svn add index.html
A index.html
~/svn/Secruity/branches/my_branch# svn commit -m "add index.html"
Adding index.html
Transmitting file data .
Committed revision 10.

#4.切换到 trunk,执行 svn update,然后将 my_branch 分支合并到 trunk 中。
svn merge ../branches/my_branch/

#5.此时可以看到 trunk 中已经多了 my_branch 分支创建的 index.html 文件。然后将合并好的 trunk 提交到版本库中。
svn commit -m "add index.html"


(7) SVN 标签(tag)
描述;通过使用 tag 的概念,我们可以给某一个具体版本的代码一个更加有意义的名字。

1
2
3
4
5
6
7
8
9
10
11
12
#1.我们在本地工作副本创建一个 tag。
svn copy trunk/ tags/v1.0

#2.新的目录将会被创建在 tags 目录下。
ls tags/
ls tags/v1.0/

#3.查看状态
svn status

#4.提交tag内容
svn commit -m "tags v1.0"