SVN高级教程

本文来自慕课网 SVN从入门到放弃

1. 课程介绍

1. 版本控制简介

版本控制是一种软件工程技巧,确保不同人所编辑的同一代码文件都得到同步。

2. 版本控制工具简单比较

特性CVSSVNGIT
并发修改支持支持支持
并发提交不支持支持支持
历史轨迹不支持更名支持支持
分布式不支持不支持支持
  • CVS由RCS发展而来。RCS不支持并发修改。假如用户A操作文件a,文件a锁定,用户B无法操作,用户A操作完成提交后,用户B才能操作。CVS在此基础上做了优化,做到了支持并发修改操作。
  • 并发提交:CVS是每个都依次提交,每个文件都记录对应的版本号。占用磁盘空间,但便于定位bug;SVN和GIT支持并发提交,多个文件一起提交,会被标记为一个版本号。节省磁盘,但搜索bug需要挨个文件检查,比较费时。
  • 历史轨迹:假如一个文件名修改,CVS无法追踪到修改文件名之前的历史版本;SVN和GIT可以追踪到所有历史版本
  • 分布式:是否需要一台专门的服务器运行版本控制系统。CVS和SVN属于集中式版本控制系统,需要专门的服务器来运行版本控制系统;GIT属分布式,不需要专门服务器去运行,每个开发人员各自的电脑组成的网络就可以运行GIT,特别适合源代码的发布和交流。很多开源项目都使用GIT,比如GitHub、Gitlab。
  • 根据应用场景选择不同的版本控制工具。一些超大型项目往往会在GIT的基础上再加一层SVN来实现更复杂的版本控制需求。

2. SVN服务端及客户端环境搭建

1. SVN的安装(Linux)

安装前更新yum源。

Ubuntu:

apt-get install subversion

CentOS:

yum install subversion

Subversion 软件包内已包含服务端和客户端两个部分。

2. 服务端命令与客户端命令

1. 服务端命令

  • svnserve:控制SVN系统服务的启动等
  • svnadmmin:版本库的创建/导出/导入/删除等
  • svnlook:查看版本库的信息等

2. 客户端命令

  • svn:版本库的检出/更新/提交/重定向等

3. 版本库的创建与删除

创建版本库

svnadmin create /path/repos
  • 绝对路径和相对路径都可以
svnadmin create --fsfs-type xxxx
  • 数据保存类型:fsfsdbd两种,推荐fsfs

删除版本库

rm -rvf /path/repos

4. 版本库配置及权限分组

1. 配置文件

配置文件位于 /path/repos/conf

  • authz:配置用户组以及用户组权限
  • passwd:配置用户名和密码
  • svnserver.conf:配置默认权限、权限配置文件及密码配置文件

2. SVN的更新和提交

update_commit

  • 更新 update:从服务器把代码下载到本地
  • 提交 commit:把本地代码提交到svn服务器,然后写入版本库(两个操作)

3. 配置文件介绍

vi svnserver.conf

[general]

# anon-access = read	指未验证(没有用户名密码)的用户访问该版本库时拥有的权限
# auth-access = write	指已验证(有用户名和密码)的用户方法该版本库时拥有的权限
  • 权限选项有三个:none(什么都没有)、read(允许更新代码)、write(允许提交代码)。配置时需要把该两行的注释去掉(去掉前边的 # 号),才可以生效

以下两个配置文件可以放到别的目录下,也可以改名,只要路径配置正确即可。这两个文件必须具备可读写权限。

# password-db = passwd	指定用户的用户名密码配置的文件路径,支持绝对/相对路径
# authz-db = authz	指定权限分组配置的文件路径,支持绝对/相对路径
vi passwd

[users]

isvn = 123456
  • 用户名 = 密码。指创建一个用户名为 isvn 密码为123456的用户
vi authz

[aliases] 配置别名,忽略

[group] 用户组配置

pm = isvn
dev = isvn2,isvn3
rookie = isvn4
  • 组名 = 用户名列表,比如 group1 = user1,user2,user3

[ / ] 版本库根目录,该权限适用于所有指向该配置文件的版本库

@pm = rw
@dev = r
@rookie = r

[isvn:/] 版本库名:/:指只适用于版本库名为isvn版本库的权限

@pm = rw
isvn2 = rw
isvn3 = r
isvn4 = 	# 什么权限都没有
  • @pm = rw 组权限,组名前加@,r --更新;w --提交
  • isvn2 = rw 用户权限,用户名 = 权限,空则没有任何权限

[repo:/xxx] 指定某个版本库下某个路径的权限(更详细的设置权限)

* = r

5. 版本库的访问

访问svn版本库

  • svn属于集中式版本控制系统,一台svn服务器服务于多台svn客户端
  • svn是跨平台的,其服务端和客户端可以搭建在Windows、Linux、macOS等任意操作系统的机器上,相互不受影响

1. 访问SVN版本库方式

  • 命令行方式访问
  • 图形可视化操作

2. 开启SVN服务

svnserve -d -r /path

3. 访问SVN版本库

客户端:

1. 检出版本库

检出版本库作用:在本地创建一个工作副本

1. 命令行方式检出版本库:

创建文件夹(svntest)用于存放工作副本

mkdir svntest
cd svntest

检出版本库:

svn checkout svn://ip --username 版本库名 --password 密码	# 缩写: svn checkout --> svn co
或者
svn checkout svn://ip	# 后续会提示输入操作系统密码、版本库密码

# ip后正常是ip:port,如果端口不写,则端口默认3690

会出现

取出版本 0。

ll 查看一下会有一个.svn的文件夹。

2. 图形可视化工具检出版本库:

操作工具:TortoiseSVN

下载地址:https://tortoisesvn.net/ 进行安装客户端

Windows桌面创建文件夹 svntest

选中该文件夹后鼠标右击选择“检出svn”

填写版本库url、版本库路径、检出目录

  • 注意:前面的协议名称是svn

点击确定后输入svn用户名、密码,之后就会自动检出

完成后文件夹上有个绿色的对号就完成了,可进入查看

  • 如果显示为空,就打开“取消隐藏文件”
小结:
  • Windows系统,建议使用小乌龟软件(TortoiseSVN)
  • Linux系统,建议使用命令行方式访问

6. SVN服务自启动

服务自启动:开启自动启动

Linux有具体的文件,根据 系统启动级别 分别对指定软件进行启动

Ubuntu自启动脚本文件:/etc/rc.local
local文件

  • 该文件保存了所有的自启动服务

exit 0 之前添加svn启动的命令:
svnserve -d -r /path

保存退出即可。

也可以单独创建自启动脚本文件。

3. SVN基本操作

1. SVN常见术语及文件状态

常见的,并不是所有的

1. 常见术语

版本库:svn版本库

检出:checkout操作,把svn版本库文件下载到本地

工作副本:checkout下载下来的文件夹,称为工作副本

更新:更新update操作,把svn版本库数据同步到本地,直接更新会更新到最新版本,也可以通过命令行方式更新到指定版本

提交:提交commit操作

版本:svn版本库的版本

版本号:svn文件的版本号码,从0开始。客户端进行commit提交操作,版本号会+1

2. 文件状态

无版本控制:新增代码文件或修改文件代码等操作后的状态

增加:对文件进行版本控制,进行增加操作后的状态

修改modify,把更新update下来的代码做修改操作后的状态

常规:checkout的版本库文件,未操作过的状态;或commit之后与svn库版本一致的状态

冲突:本地工作副本和svn版本库的版本不一致,本地修改后做提交操作引发冲突

删除missing,本地删除文件或目录

锁定

建议:

  • 养成经常更新的好习惯,让工作副本和版本库尽可能的保持一致
  • 在开发中最大程度的避免数据冲突

2. checkout 和 export 区别

checkout:检出

  • checkout 检出的工作副本目录中含.svn文件夹
  • 版本控制中有一种文件状态:无版本控制
svn checkout -r 2	# 检出版本2
  • 如果单纯 svn checkout 会检出最新版本

export:导出

  • 导出项目不存在 .svn 文件夹
svn export -r 3	# 导出版本3

小结:

  • checkout检出的工作副本是在版本控制之内;

  • export导出的项目文件不在版本控制之内

  • checkout --> .svn + 项目文件

  • export --> 项目文件

  • export导出的文件不能称之为工作副本

checkout与export的区别和使用

  • .svn 记录着工作副本最后一次更新后的文件状态
  • .svn 标记工作副本的一切变化

3. add、ci、up、del

注意: 使用svn命令时要注意自己使用的是服务端命令还是客户端命令。

常见SVN客户端命令

命令说明
svn add把无版本控制的文件添加到版本控制
svn commit提交修改到服务器,创建一个新版本号
svn update更新工作副本。特性:默认情况下,每个文件只会从服务端更新一次最新版本
svn delete从版本库中删除文件或目录

**demo:**本地新建了一个 index.html、css文件夹(内部包含a.css和b.css)、js文件夹(内部包含a.js和b.js)

add

用户1

  • 把 index.html 添加到版本库:

    # 语法: svn add 文件名
    svn add index.html
    
  • 把 css 文件夹添加到版本库:

    svn add css
    
    • 该操作会把css整个文件夹(包括a.css和b.css)递归添加到版本库
  • 把当前目录下所有无版本控制的文件和目录都增加到版本控制里

    svn add * --force
    
    • --force参数会强制扫描所有已添加和未添加文件和文件夹下的所有文件,属无版本控制的进行增加操作;
    • 如果没有force参数,就不会把css下的a.css和b.css增加到版本控制里,因为css文件夹已添加,它就不会再去扫描该文件夹内的文件
  • 把js空文件夹添加到版本库:

    # 语法: svn add 文件名 --non-recursive
    svn add js --non-recursive
    
commit
  • 提交文件到svn版本库:

    # 语法:svn commit -m "注释说明" 文件名
    svn commit -m "添加index.html文件" index.html
    
    • commit 可缩写为 ci,注释说明可省略,但双引号要有不能省略

用户2

update
  • 更新文件到本地

    svn update
    
    • update 缩写 up

4. add、ci、up、del - up

  • 查看某个版本的某个文件。

    # 语法: svn up -r 版本号 文件名
    svn up -r 1 index.html
    
    • 如果index.html当前版本是2,使用一次svn up -r 1 index.html后,再执行2不会继续更新至2
  • 强制把所有文件更新至最新版本

    svn up *
    
    • svn up 默认只更新一次
del
  • 删除 index.html

    # 语法: rm 文件名
    rm index.html
    
  • 再执行 svn up 会把 index.html 恢复,因为 Linux删除和 svn删除是两回事

svn up :

  • 默认情况下只更新一次。如果当前最新版本是2,执行一次更新1后再更新不会更新到版本2

  • 当工作副本缺失某个文件时,使用该命令后,服务端还是会把缺失文件的最新版本更新到本地。

  • 如果一个文件被更新至某个版本,之后想更新到最新版本,可以先rm本地文件,然后执行该命令更新至最新版本。

  • 删除版本库中的文件

    svn delete 文件名 -m "注释说明"
    svn remove 文件名 - m "注释说明"
    
    • delete 缩写 del;remove 缩写 rm
    • 删除命令后的-m "注释说明"可省略
  • 删除后记得提交

    svn ci -m ""
    

5. diff、mkdir、cat_1

常见客户端命令

命令说明
svn diff版本差异比较
svn mkdir创建目录并增加到版本控制
svn cat不检出工作副本直接查看指定文件
diff

比较两个文件的不同

  • 比较当前版本和工作副本的差异

    • 语法:svn diff 文件名(diff 缩写 di)
    # 比较index.html文件当前版本和工作副本的差异
    svn di index.html
    # 返回内容如下:
    Index: index.html
    --- index.html  (revision 3)	# 前边减号指最后一次更新得到的版本3的内容
    +++ index.html  (working copy)	# 前边加号指工作副本中被修改的内容,working copy: 工作副本
    @@ -0,0 +1,12 @@	# 0,0表示原文件;1,12表示文件存在差异的行号,存在差异的是第1到第12行
    # 再下边的内容是该文件存在差异的内容
    
    • 行头-号表示修改前的内容;行头+号表示修改后的内容,即工作副本的内容;行头无符号表示该行无变化
    • 提交该文件时,svn会把-号行删掉,把+号行添加
  • 指定版本和工作副本的比较

    # 比较index.html文件版本2和工作副本差异
    svn di -r 2 index.html
    
  • 比较一个文件任意两个版本的差异

    # 比较index.html文件版本1和版本3的差异
    svn di -r 1:3 index.html
    
  • 比较批量文件所有版本的差异

    svn di
    
    • 该命令会比较当前目录下所有文件的所有版本的差异(不推荐)
mkdir
  • 创建doc文件夹并添加到svn版本库中

    # 语法:svn mkdir 目录名
    svn mkdir doc
    
cat

可脱离工作副本的目录执行(就是不在svn目录下执行)

  • 查看index.html文件内容

    # 语法:svn cat svn://ip/文件名
    svn cat svn://192.168.0.130/index.html
    

6. 工作副本还原 revert

称为:SVN版 Ctrl + z,即还原工作副本至最后一次更新得到的版本文件。

语法:svn revert [--recursive] [filename|*]

  • 恢复 index.html 为最后一次更新得到的版本文件

    svn revert index.html
    
  • 恢复当前目录下的所有文件(当前目录下有文件夹的话不会递归扫描文件夹下的文件)

    svn revert *
    
  • 恢复当前目录下的所有文件、文件夹及其文件

    svn revert --recursive *
    

7. 二进制冲突与树冲突

1. 什么是冲突以及冲突的产生条件

什么时候产生冲突: 冲突常出现于工作副本长时间未更新时

冲突产生的原因: 更新到的数据与工作副本的修改正好在同一地方

1. 二进制冲突

冲突

2. 树冲突
  • 发生树冲突的文件都不是二进制文本文件

  • 树冲突无法精确到行,并且处理树冲突必须处理整个文件

2. 如何尽可能的避免冲突

养成经常更新的好习惯,让工作副本和版本库尽可能的保持一致。

3. 如何解决冲突

情景: 假设用户A和用户B都update了最新的代码,用户A和用户B都修改了index.html的第5行,之后用户A先commit,svn版本从0更新到1,用户B在版本0的前提下commit,会报该文件is out of date,从而引发了冲突。

使用svn up查看冲突情况

会有Select选项:

Select
(p) postpone, (df) show diff, (e) edit file, (m) merge
(mc) my side of conflict, (tc) their side of conflict,
(s) show all options:
  • (mc): 保留我自己的版本

  • (tc): 保留别人的版本

  • ( p): 推迟提交(推荐)
    选择该选项,会提示冲突文件,svn会把冲突信息发送给与自己发生冲突的用户,不会影响线上,冲突只会存在于冲突用户的工作副本中

  • (e): 编辑文件
    修改完按 ctrl + x 退出

  • (df): 比较差异

    <<<<<<<<.mine
    自己的代码
    ========
    发生冲突的代码,即别人提交的代码
    >>>>>>>> .r5
    

使用命令的方式修改冲突文件

# 语法: svn resolve 文件名
svn resolve index.html
  • 会弹出选项信息

注意: 冲突处理完需要告诉服务端冲突已解决,否则服务端会一直记录该冲突。

# 语法: svn resolved 文件名
svn resolved index.html
  • 使用直接编辑冲突文件的方式处理冲突,处理完必须要执行该步骤
  • 使用命令的方式(resolve)处理冲突,处理完不需要再执行该步骤

8. 锁定lock与解锁unlock

svn lock 文件名: 锁定文件,防止其他成员对文件进行提交
svn unlock 文件名: 解锁文件

优点:用户锁定一个文件并对其编辑,编辑完后再解锁,可有效防止冲突;

缺点:如果多个用户同时操作同一文件的不同行,有一个用户对该文件进行锁定会影响其他用户的开发,导致团队开发效率降低。

demo

  • user1锁定index.html
svn lock index.html
# 返回信息:
'index.html' locked by user 'user1'
  • user2编辑index.html,这个是没问题的,保存后提交
svn ci -m "" index.html
# 返回信息:
失败,User user2 does not own lock on path '/index.html' (currently locked by user1)
  • user1解锁index.html文件
svn unlock index.html
# 返回信息:
'index.html' unlocked.
  • user2提交index.html文件
svn ci -m "" index.html
# 返回成功

注意:

  • 如果用户锁定文件后进行编辑,编辑完进行commit,文件会自动解锁,不用再执行svn unlock命令。
  • 如果用户锁定文件,提交后不想该文件自动解锁,则提交命令改为:
    svn ci -m "" --no-unlock index.html

4. SVN进阶应用

1. ls、st、log、info

命令说明
svn list (缩写 svn ls)列出当前目录下处于版本控制的所有文件(夹)
svn status (缩写 svn st)列出工作副本中的文件(夹)的状态
svn log查看提交日志(来自 svn ci 的 -m 参数)
svn info工作副本及文件(夹)的详细信息

svn list

# 准备工作:	.svn同目录下创建 test.html

svn ls
# 可以查看到除test.html之外的工作副本的文件(夹),文件夹内部文件不显示

svn ls --recursive
# 可以看到包含test.html在内的所有本目录下的文件、文件夹及其内部所有文件

svn ls -v 或 svn ls -v --recursive
# 查询当前目录所有文件的详细信息,类似于Linux的`ll`命令

svn status

以下状态不是所有的

状态说明
?无版本控制,未加到版本控制中
D已被标记从版本库中删除
M已被编辑过
A已被标记增加到版本控制中
R文件被替换(指文件用svn rm删除后,又创建了同名字的文件添加到版本库中)
C文件存在冲突
!文件缺失(指本地删除但svn版本库未删除)
  • svn update 执行后会出现 U 标记,status里不包含

svn log

  • 查看指定文件的提交日志

    svn log index.html
    

svn info

  • 查看某个指定文件(夹)的信息

    svn info index.html
    
  • 使用xml格式显示指定文件的信息

    svn info index.html --xml
    
  • 使用Linux管道保存xml格式显示出的指定文件的信息

    svn info --xml >> info.xml
    
    • 这样就在该目录下生成info.xml文件

2. 多版本库解决方案-A

多版本库:一台SVN服务器上同时运行多个版本库

解决方案:创建多个版本库,手动给每个版本库服务指定不同的端口号。

端口号用途端口号
TCP/IP协议规定端口号范围0-65535
公认端口0-1023
注册端口1024-49151
私有端口49152-65535

svn默认端口号:3690

  • 修改svn端口号:

    svnserve -d -r /路径 --listen-port 端口号
    
  • 停止所有svn版本库服务

    killall svnserve
    

3. 多版本库解决方案-B

解决方案:多个版本库创建在同一目录下,启动svn服务,路径是svn版本库的上一级目录,就可以只使用一个端口号运行多个版本库。

  • 检出某个版本库

    svn co svn://ip/路径/版本库名
    
    • port不用写,默认3690

4. 多版本解决方案-总结

方式优点缺点
多个端口号版本库可以创建在任意位置端口号容易混淆
一个端口号版本库必须创建在同一目录下无需分配端口号

5. copy

部分功能:关联工作副本和操作线上svn服务

功能

  • 工作副本 → 工作副本
  • 工作副本 → 版本库(不可跨库)
  • 版本库 → 工作副本(允许跨库)
  • 版本库 → 版本库(不可跨库)

注意:提交无法跨库

1. 工作副本 → 工作副本

  • 复制工作副本中的index.html到工作副本

    # 语法:svn copy 原文件名 目标文件名
    # copy 缩写: cp
    svn cp index.html copy.html
    A 	copy.html
    
    • 如果使用Linux原生复制命令,复制得到的文件是无版本控制状态,需使用svn add 添加到版本控制状态
  • 复制工作副本中的index.html的指定版本到工作副本

    # 语法:svn cp -r 版本号 原文件名 目标文件名
    svn cp -r 4 index.html
    
  • 复制批量文件到指定文件夹

    # 创建目标文件夹
    svn mkdir temp
    # 复制文件到temp文件夹
    # 语法:svn cp 文件1 文件2 ... 目标文件夹路径
    svn cp index.html about.html ./temp
    
    • 多个文件名之间用空格隔开

2. 工作副本 → 版本库

  • 复制工作副本中的index.html到版本库

    # 语法:svn cp 原文件名 svn://ip/路径/目标文件名 -m "提交备注"
    svn cp index.html svn://192.160.0.130/imooc/target.html -m "copy a file"
    
    • 不通过工作副本直接提交到版本库,之后需要进行svn update进行更新
    • 上边的命令也可以通过-r指定版本号

注意:从工作副本复制到版本库不支持跨库操作。即检出的工作副本只能复制到被检出的版本库中

3. 版本库 → 工作副本

  • 从线上版本库中复制index.html文件到工作副本,取名为demo.html

    # 语法:svn cp svn://ip/路径/原文件名 目标文件名
    svn cp svn://192.168.0.130/imooc/index.html demo.html
    

注意: 从线上版本库复制到本地工作副本支持跨库操作。

  • 比如:从线上a版本库复制文件到本地b工作副本中

    svn cp svn://192.168.0.130/hello/index.html demo2.html
    

4. 版本库 → 版本库

  • 把svn版本库根目录下的文件复制到版本库某个文件夹下
# 语法:svn cp svn://ip/原文件路径 svn://ip/目标路径(跟原文件同库,因为不允许跨库) -m "提交备注"
svn cp svn://192.168.0.130/imooc/ svn://192.168.0.130/imooc/trunk -m "set a trunk"

6. 主干版本与分支版本

创建分支版本库的过程是脱离工作副本的,跟工作副本无关。

创建分支版本,通常会在版本库中增加一层目录,用来区分主干版本和分支版本。

  • 创建分支版本
# 把svn版本库根目录下的文件复制到文件夹
# 语法:svn cp svn://ip/原文件路径 目标路径(跟原文件同库,因为不允许跨库) -m "提交备注"
svn cp svn://192.168.0.130/imooc/ svn://192.168.0.130/imooc/trunk -m "set a trunk"
# 进入imooc中执行update更新工作副本
cd imooc/
svn up
# 可看到工作副本目录里增加了trunk目录,里边是原imooc中所有文件
# 创建branch分支版本
# 语法:svn cp svn://ip/主干版本文件路径 svn://ip/分支版本文件路径 -m "提交备注"
svn cp svn://192.168.0.130/imooc/trunk svn://192.168.0.130/imooc/branch -m "create a branch"
# 然后更新
svn up

注意

一般在创建项目后,还未开始开发时就会创建出主干版本(trunk)、分支版本(branch)和版本备份(tag,用来对每个主干版本发布后的项目文件备份),这样互不干扰。

5. SVN高级应用

svn高级应用属管理员级别操作,需要暂停 SVN 服务。

1. hooks

钩子:当执行某些特定操作时触发执行预先设定好的任务。

例如:论坛用户进行登录、发帖、回帖等操作,会送金币。这些操作好比 特定操作,送金币好比 设定好的任务,特定操作像钩子一样钩住设定好的任务。

svn根目录下有hooks文件夹,内部有很多以.tmpl格式(template)的文件,本质是shell脚本。这些是钩子的模板文件,使这些钩子文件生效,只需复制一份,把.tmpl后缀去掉就可以启用。

hooks目录下的.tmpl文件:(三个时间点)

  • start开头的文件:数据传输开始之前执行

  • pre开头的文件:数据传输之后,写入版本库之前执行

  • post开头的文件:写入版本库之后执行

  • 文件名后半部分是执行的操作

    • commit:提交
    • lock:锁定
    • unlock:解锁
    • revprop-change:版本属性变化
  • 执行post-commit.tmpl文件:

    # 复制该文件
    cp -a post-commit.tmpl post-commit
    # 给post-commit文件增加可执行权限
    chmod +x post-commit
    # 查看文件状态
    ll
    # 可看到绿色的 post-commit* 表示已经有了可执行的权限
    
  • demo:编辑post-commit文件,每一次commit操作使svn版本更新后,把最新版本信息写入指定xml文件内,保存到某个服务器上,可以让用户使用浏览器访问查看

# 编辑post-commit文件
vi post-commit
# 该文件最后有三行非注释信息,删掉,自己编写
# 语法: svn info svn://ip/路径 --xml >> 目标路径
svn info svn://192.168.0.130/imooc --xml >> /var/www/repo.xml
# 保存退出
wq!
# 关闭svn服务
killall svnserve
# 启动svn服务
svnserve -d -r /svnroot/
# 修改某个文件(index.html)进行commit提交,然后使用浏览器访问
# 即可显示新生成的repo.xml

钩子应用例子:把svn架设到GitHub之上,使项目的版本控制更加智能化。

2. 版本库精简与丢弃

demo:假设某项目从r1版本更新迭代到了r100,现在想丢弃r1-r20版本,保留r21-r100版本

# 停止svn服务
killall svnserve
# 备份保留版本库
svnadmin dump 版本库文件系统路径 -r 起始版本号:终止版本号 > 保存目录
svnadmin dump /svnroot/imooc/ -r 21:100 > ~/imooc
	 - ~/imooc:`~` 指返回到home目录
# 创建空版本库用于存储备份的数据
svnadmin create /svnroot/newimooc
# 把刚才备份的数据加载到空版本库
svnadmin load svnroot/newimooc/ < ~/imooc.repo
# 通过加载运行的信息可得:原来的r21变成了现在的r1,原来的r100变成了现在的r80
# 把imooc版本库的配置文件也复制到新版本库中
cp -av /svnroot/imooc/conf/* /svnroot/newimooc/conf/
# 把旧imooc版本库删除
rm -rvf /svnroot/imooc
# 把SVN服务运行起来
svnserve -d -r /svnroot/

注意

版本库精简后,当前的工作副本版本与版本库版本不匹配,需要删掉本地工作副本,重新checkout检出一份。

3. 版本库迁移与switch重定向

1. 版本库迁移

方法1

版本库迁移本质上跟版本库精简一样,版本库精简操作,使用svnadmin dump来备份版本库数据时,选定版本号范围从r1到最新版本,就等于把整个版本库完整的备份出来了,然后把生成的备份文件复制到新的服务器上,使用svnadmin load加载到新版本库里。

方法2

  • killall svnserve
  • 把 /svnroot/repo/ 压缩成 repo.zip
  • 复制 repo.zip 到新服务器并解压
  • 在新服务器上运行 repo 版本库

方法1和方法2区别

  • 版本库相当于鸟窝,版本库的外壳相当于树
  • 方法1是把鸟窝从树a挪到了树b;方法2是把鸟跟树一块挪到了别的位置

2. 版本库switch重定向

命令:svn switch --relocate 旧url 新url

  • switch 缩写 sw

重定向:工作副本会记录svn服务端的url,svn版本库迁移后,svn版本库的url发生改变,工作副本中的url就失效了,需要更新定位到新的url上

demo:压缩world版本库,并解压到另外一个位置

# 停止svn访问
killall svnserve
# 切换到svn版本库目录
cd /svnroot/
# 复制world版本库(假设newworld是从别的服务器复制过来,然后解压得到的版本库)
mv world newworld
# 运行svn服务
svnserve -d -r /svnroot/
# 进入world使用svn up更新会报错
# 进行url的重定向
svn sw --relocate svn://192.168.0.130/world svn://192.168.0.130/newworld
# 此时再更新svn就可以了
svn up

6. 课程总结 - 常见坑与总结

1. 创建完版本库忘记配置svnserve.conf

导致:版本库可以运行,但无法登录、无法检出版本库,报:认证失败

2. 运行版本库的路径问题

检出版本库时要有目录名称,运行和检出互斥,目录名称在运行时写则检出时就不要写;检出时写了则运行时就不要写,否则报版本库不存在。

3. svnadmin dump/load 管道符号问题

备份dump: 大于号 >
加载load: 小于号 <

7. 学习总结

安装svn

系统安装方式
Ubuntuapt-get install subversion
CentOSyum install subversion
windows可视化软件:TortoiseSVN

客户端命令

  • 检出svn版本库,在本地创建一个工作副本

    svn checkout svn://ip:port/path --username 版本库名 --password 密码
    
    • checkout 缩写 co
    • port 默认 3690
  • 无版本控制的文件添加到版本控制

    svn add 文件名
    
    • 文件名是 * 则表示当前目录下的所有文件
    • 参数:
      • --force: 强制扫描已添加和未添加文件与文件夹夹下的所有文件,没有该参数不会递归操作所有文件夹
      • --non-recursive: 添加空文件夹到版本控制中
  • 提交文件到版本库

    svn commit -m "提交说明" 文件名
    
    • commit 缩写 ci
    • 文件名是 *号表示提交当前目录下所有文件
  • 更新工作副本

    svn update
    
    • update 缩写 up
    • svn up * 默认只更新一次
    • 参数:
      • -r 版本号: 指定版本号
  • 从版本库中删除文件或目录 (删除后记得提交)

    svn delete 或 svn remove
    
    • delete 缩写 del; remove 缩写 rm
  • 比较版本差异

    svn diff 文件名
    
    • diff 缩写 di
    • 参数:
      • -r 版本号: 指定版本号
      • -r 版本号1:版本号2: 比较任意两个版本的差异
    • +号开头:修改过的内容;-号开头表示未修改
    • svn di 表示比较批量文件所有版本的差异(不推荐)
  • 创建文件夹并添加到版本库中

    svn mkdir 目录名
    
  • 不检出工作副本直接查看指定文件 (可脱离工作副本执行)

    svn cat svn://ip:port/文件名路径
    
  • 工作副本还原,还原至最后一次更新得到的版本文件

    svn revert 文件名
    
    • 参数:
      • svn revert *:恢复当前目录下所有的文件,当前目录有文件夹的话不会递归扫描文件夹下的文件
      • --recursive:恢复当前目录下所有文件与文件夹及其内部文件
  • 使用命令的方式修改冲突文件

    svn resolve 文件名
    
    • 会弹出选项信息
      • (mc): 保留我自己的版本
      • (tc): 保留别人的版本
      • ( p): 推迟提交(推荐)选择该选项,会提示冲突文件,svn会把冲突信息发送给与自己发生冲突的用户,不会影响线上,冲突只会存在于冲突用户的工作副本中
      • (e): 编辑文件
        修改完按 ctrl + x 退出
      • (df): 比较差异
  • 冲突解决后告知服务端冲突已解决,否则服务端会一直记录该冲突

    svn resolved 文件名
    
    • 直接编辑冲突文件的话,处理完须执行该步骤
    • 命令的方式(resolve)处理冲突,处理完不需要再执行该步骤
  • 锁定文件,防止其他成员对文件进行提交

    svn lock 文件名
    
    • 优点:有效防止冲突
    • 缺点:如果多个用户同时操作同一文件的不同行,有一个用户对其锁定,会影响团队开发效率
  • 解锁文件

    svn unlock 文件名
    
    • 若用户锁定文件后编辑再commit,文件自动解锁,无需再执行解锁

    • 若用户锁定文件,提交后不想该文件自动解锁,执行:

      svn ci -m "" --no-unlock 文件名
      
  • 列出当前目录下处于版本控制的所有文件(夹)

    svn list
    
    • list 缩写 ls
    • 参数:
      • recursive: 查看当前目录下所有文件和文件夹及内部所有文件,没有该参数,文件夹内文件不显示
      • -v: 查询当前目录所有文件的详细信息,类似于Linux中ll命令
  • 列出工作副本中的文件(夹)的状态

    svn status
    
    • status 缩写 st
    • 状态:
      • ?: 无版本控制,未加到版本控制中
      • D: 已被标记从版本库中删除
      • M: 已被编辑过
      • A: 已被标记增加到版本控制中
      • R: 文件被替换(指文件用svn rm删除后创建了同名的文件并添加到版本控制中)
      • C: 文件存在冲突
      • !: 文件缺失(指本地删除但svn版本库中未删除)
    • svn update 执行后会出现U标记,status里不包含
  • 查看提交日志

    svn log 文件名
    
  • 查看工作副本及文件(夹)的详细信息

    svn info 文件名
    
    • 参数:
      • --xml: 使用xml格式显示指定文件的信息
    • 使用Linux管道保存xml格式显示出的指定文件的信息
      svn info --xml >> info.xml
      - 会在该目录下生成info.xml
  • copy复制功能(copy缩写cp)

    • 工作副本 → 工作副本

      svn cp 原文件名 新文件名
      
      • 参数:
        • -r 版本号 指定版本
          svn cp -r 版本号 原文件名 新文件名
      • 复制批量文件到指定文件夹
      	# 创建文件夹
      	svn mkdir 指定文件夹
      	# 批量复制
      	svn cp file1 file2 ... 指定文件夹
      	```
      
      
    • 工作副本 → 版本库(不可跨库)

      svn cp 原文件名 svn://ip:port/path/新文件名 -m "复制注释"
      
      • 参数:-r 版本号 指定版本
    • 版本库 → 工作副本(可跨库)

      svn cp svn://ip:port/path/旧文件名 新文件名
      
    • 版本库 → 版本库(不可跨库)

      svn cp svn://ip:port/原文件路径 svn://ip:port/新文件路径 -m "复制注释"
      
  • 创建分支版本(创建项目后就创建主干版本、分支版本、版本备份)

    # 把svn版本库根目录下的文件复制到文件夹
    svn cp svn://ip:port/path svn://ip:port/path/arm_path -m "注释"
    # 进入arm_path中执行update更新工作副本
    cd arm_path
    svn up
    # 创建分支版本branch
    svn cp svn://ip:port/path/arm_path svn://ip:port/path/branch -m "创建分支注释"
    # 最后更新
    svn up
    

服务端命令

  • 创建svn版本库

    svnadmin create /path/repos
    
    • 参数:
      • --fsfs-type: 数据保存类型:fsfs和dbd,推荐fsfs
  • 开启svn服务

    svnserve -d -r /path
    
  • 停止所有svn服务

    killall svnserve
    
  • 删除版本库

    rm -rvf /path/repos
    
  • 修改svn端口号

    svnserve -d -r /path --listen-port 端口号
    
  • 执行hooks钩子文件 (以post-commit.tmpl为例)

    # 复制文件
    cp -a post-commit.tmpl post-commit
    # 给post-commit文件增加可执行权限
    chmod +x post-commit
    
     - hooks钩子文件自定义例子:每次commit操作后,把最新版本信息写入指定xml文件内,保存到某个服务器上,用户可通过浏览器访问查看
    # 编辑post-commit文件
    vi post-commit
    # 该文件最后三行非注释信息删掉,然后写入
    svn info svn://ip:port/path --xml >> /目标路径/demo.xml
    # 保存退出
    wq!
    # 关闭svn服务
    killall svnserve
    # 启动svn服务
    svnserve -d -r /path
    

知识点

svn配置信息

  • svn配置信息位于 /path/repos/conf
  • svn配置权限:none-无权限(为空);read-允许更新代码;write-允许提交代码
  • svn配置信息:
    • svnserver.conf:配置默认权限、权限配置文件及密码配置文件
      • [general] : anon-access 未验证用户权限;auth-access 已验证用户权限;passwd-db 用户名密码配置文件路径;authz-db 权限分组配置文件路径
    • passwd: 配置用户名密码
      • [users] 用户名密码:username = password 用户名 = 密码
    • authz: 配置用户组以及用户组权限
      • [aliases] : 配置别名,可忽略
      • [group] 用户组权限:group = username 组名 = 用户名1,用户名2,…
      • [/] 版本库根目录:该权限适用于所有指向该配置文件的版本库,指定用户组权限时,组名前加@
      • [版本库名:/] 指定特定版本库的权限,指定用户组权限时,组名前加@
      • [repo:/xxx] 指定某个版本库下某个路径权限, * = r

配置svn自启动

/etc/rc.local 在 exit 0 之前添加下行代码

svnserve -d -r /path

checkout 和 export:

  • 使用:
    • 检出某个版本:svn checkout -r 2
    • 导出某个版本:svn export -r 2
  • 区别:
    • checkout 检出的工作副本在版本控制范围内,有 .svn 文件夹
    • export 导出的项目文件不在版本控制范围内,没有 .svn 文件夹

版本冲突

  • 什么时候产生冲突:常出现于工作副本长时间未更新时
  • 产生冲突原因:更新到的数据与工作副本的修改正好在同一地方
  • 冲突分类:二进制冲突、树冲突
  • 如何解决冲突:
    • 方式1:svn up列出Select选项,根据提示修改
      • 修改后执行 svn resolved 文件名告诉svn服务器冲突已处理
    • 方式2:使用命令的方式修改: svn resolve 文件名

多版本库解决方案

方案A

一台SVN服务器上同时运行多个版本库,创建多个版本库,手动给每个版本库指定不同的端口号。

svnserve -d -r /path --listen-port 端口号	# 默认3690

说明:版本库可创建在任意位置;端口号容易混淆

方案B

多个版本库创建在同一目录下,启动SVN服务,路径是SVN版本库的上一级目录,可只使用一个端口号运行多个版本库。

svn co svn://ip:port/path/版本库名    # port不用写,默认3690

说明:版本库必须创建在同一目录下;无需分配端口号

版本库精简与丢弃

假设某项目从r1更新迭代到r100,现想丢弃r1-r20保留r21-r100版本

# 停止svn服务
killall svnserve
# 备份保留版本库
# 语法:svnadmin dump 版本库文件系统路径 -r 起始版本号:终止版本号 > 保存路径
svnadmin dump /svnroot/isvn/ -r 21:100 > ~/isvn
# 创建空版本库用于存储备份的数据
svnadmin create /svnroot/newisvn
# 把刚才备份的数据加载到空版本库中(执行后原来的r21变成了现在的r1,原来的r100变成现在的r80)
svnadmin load svnroot/newisvn < ~/isvn.repo
# 把isvn版本库的配置信息也复制到新版本库中
cp -av /svnroot/isvn/conf/* svnroot/newisvn/conf/
# 把旧isvn版本库删除
rm -rvf /svnroot/isvn
# 把svn服务运行起来
svnserve -d -r /svnroot/
# 版本库精简后,当前工作副本版本与版本库版本不匹配,需要删掉本地工作副本,重新checkout一份

版本库迁移

方法1: 使用svnadmin dump备份数据库时版本号范围从r1指定到最新版本,然后把生成的备份文件复制到新的服务器上,使用svnadmin load加载到新版本库中。

方法2: 停掉svn服务,把svn下的repo压缩成repo.zip,将其复制到新服务器上并解压,然后在新服务器上运行repo版本库。

版本库switch重定向(switch缩写sw)

# 停止svn服务
killall svnserve
# 切换到svn版本库目录
cd /svnroot/
# 复制x版本库
mv isvn newisvn
# 运行svn服务
svnserve -d -r /path
# 进行url的重定向
# 语法:svn switch --relocate 旧url 新url
svn sw --relocate svn://192.168.0.130/isvn svn://192.168.0.131/newisvn
# 更新svn
svn up
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员老五

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值