svn使用教程
前言
SubVersion基础教程,从用户角度学会使用svn进行版本控制。
基本概念
1. 什么是SubVersion?
SubVersion简称svn,是一个开源的版本控制系统(version control system),svn可以跨越时间对文件和目录的修改进行管理。
2. 分布式和集中式
***集中式的版本控制(centralized version control)***:如svn,主要特点是有一个远程的主仓库,仓库存放了被版本控制的数据,用户在本地操作数据的浅拷贝副本。
***分布式版本控制(distributed version control)***:如git,不需要一个远程的中央仓库,每一个用户在本地都有一份完整的版本历史。用户之间写作不要远程的中央节点,可以直接进行交互。
3. 仓库
仓库是版本控制系统的核心,用来存放系统数据。仓库通常是以文件树(filesystem tree)的形式存放信息,文件系统树是文件和目录的分层结构。仓库中的文件是人类不可读的。
4. 工作副本
工作副本(working copy) 仓库指定版本数据在本地的副本,用户可以对它进行操作,对其它软件来说工作副本只是一个普通的本地目录。工作副本中存放一个 .svn 文件夹用来存放版本控制信息。
5. 版本号
svn每个版本都会对应一个唯一的版本号, SVN版本号会随着提交不多的增多,版本号渐渐增大。可以使用版本号访问项目指定版本文件的快照,但是一般操作无需考虑版本号,除非对指定版本操作。用户可以在提交的日志中查看版本号。
除了使用整数指定版本号外,svn还支持另外两种指定版本号的形式:版本号关键字***和***版本号日期
6. svn组件
- svn: 客户端命令行工具。
- svnversion:用与报告工作副本状态。
- svnlook:用于检查仓库的工具。
- svnadmin:用于创建、调整或修复仓库工具。
- mod_dav_svn:可插拔的Apache HTTP服务器模块。
- svnserve:svn服务程序,可以以守护进程的方式运行,也可以被ssh调用。
- svnsync:可以跨网络对仓库进行增量镜像备份的程序。
可以使用 组件名 -h查看组件参数说明。
服务器搭建
1. 安装配置svn
svn安装和配置修改教程网上较多,不在赘述。
2. 创建代码仓库
安装好svn之后,我们首先需要创建一个目录,专门用来存放我们的仓库。
mkdir /repos
现在我们需要建立一个***代码仓库***,用来做版本控制,它的名字叫***MyNote***:
root@svn-server:/repos# svnadmin create /repos/MyNote
进入到/repos/MyNote仓库中,发现其中有几个目录:
root@svn-server:/repos/MyNote# ls
conf db format hooks locks README.txt
其中conf是仓库配置和权限相关;db是用来存放数据;hooks是svn的钩子相关目录;locks是锁相关,现在我们进入到conf中:
root@svn-server:/repos/MyNote# cd conf/
root@svn-server:/repos/MyNote/conf# lt
total 20
-rw-r--r-- 1 root root 4375 Sep 28 03:32 svnserve.conf
-rw-r--r-- 1 root root 309 Sep 28 03:32 passwd
-rw-r--r-- 1 root root 885 Sep 28 03:32 hooks-env.tmpl
-rw-r--r-- 1 root root 1080 Sep 28 03:32 authz
在svnserve.conf中添加:
anon-access = none
auth-access = write
password-db = passwd
authz-db = authz
在password中添加一个用户admin,密码为clear:
[users]
admin = clear
然后在authz文件中创建一个用户组g_manager,将admin添加到该用户组中,并且指定仓库MyNote根目录下的权限:
[groups]
g_manager = admin
[MyNote:/]
@g_manager = rw
* =
- @g_manager 表示g_manager是一个用户组,而不是用户;
- *= 表示除了@g_manager的rw权限,其它所有用户或者用户组或者others对MyNote仓库的根目录的访问权限都为空。这里的根目录其实就是MyNote自己。
- svn的优点就是可以很精细控制目录权限,基于svn下级目录会继承上级目录的权限,可以有两种模式,第一种是上级目录默认权限为空,然后手动展开设置到权限控制的目录添加指定成员访问权限,开发人员可以直接检出根目录获取所有有权限的下级目录,对开发人员比较友好,但是配置文件目录展开会比较复杂;第二种是只开放开发人员有权限的目录,开发人员需要一个一个的检出自己需要的文件,操作比较复杂,但是目录权限配置文件会比较简单;这里不做展示
到目前为止,我们已经在repos目录中创建了一个空的代码仓库MyNote,下面我们启动svn使用我们创建的用户来访问svn查看是否有效:
svnserve -d -r /repos
然后我们随便找个路径,检出MyNote试一下:
svn@svn-server:~/333$ svn checkout svn://localhost/MyNote
Checked out revision 0.
可以正常使用,因为MyNote是一个空的仓库,因此我们检出了revision 0;
3.项目导入
下面我们在本地创建一个普通的目录MyNote,其目录结构如下,现在我们将它的目录结构导入到上面创建的仓库MyNote中:
└── MyNote
├── project1
│ ├── branches
│ ├── tags
│ └── trunk
├── project2
│ ├── branches
│ ├── tags
│ └── trunk
├── project3
│ ├── branches
│ ├── tags
│ └── trunk
├── project4
├── branches
├── tags
└── trunk
MyNote下面包含了四个项目project1、project2、project3和project4,每个项目下面都含有tags,trunk,branches三个目录,创建好目录后将其导入到代码仓库中
svn@svn-server:~/tt$ svn import MyNote/ svn://localhost/MyNote
Log message unchanged or not specified
(a)bort, (c)ontinue, (e)dit:
c
Adding MyNote/project1
Adding MyNote/project1/branches
Adding MyNote/project1/tags
Adding MyNote/project1/trunk
Adding MyNote/project2
Adding MyNote/project2/branches
Adding MyNote/project2/tags
Adding MyNote/project2/trunk
Adding MyNote/project3
Adding MyNote/project3/branches
Adding MyNote/project3/tags
Adding MyNote/project3/trunk
Adding MyNote/project4
Adding MyNote/project4/branches
Adding MyNote/project4/tags
Adding MyNote/project4/trunk
Committing transaction...
Committed revision 1.
然后然后上面checkout出来的工作副本里面更新一下,查看我们导入的代码是否加入了仓库中。
svn@svn-server:~/333/MyNote$ svn up
Updating '.':
A project1
A project1/branches
A project1/tags
A project1/trunk
A project2
A project2/branches
A project2/tags
A project2/trunk
A project3
A project3/branches
A project3/tags
A project3/trunk
A project4
A project4/branches
A project4/tags
A project4/trunk
Updated to revision 1.
成果更新到reversion 1的版本,获取到了我们添加的四个项目的代码结构,后面我们就可以对这四个项目开发的时候进行代码管理啦。
基本操作
1. 查询帮助手册
使用 svn help
打开内置文档入口:
svn@svn-server:~/MyNote$ svn help
usage: svn <subcommand> [options] [args]
Subversion command-line client.
Type 'svn help <subcommand>' for help on a specific subcommand.
Type 'svn --version' to see the program version and RA modules,
'svn --version --verbose' to see dependency versions as well,
'svn --version --quiet' to see just the version number.
Most subcommands take file and/or directory arguments, recursing
on the directories. If no arguments are supplied to such a
command, it recurses on the current directory (inclusive) by default.
Available subcommands:
add
auth
blame (praise, annotate, ann)
cat
changelist (cl)
checkout (co)
...
查询单个命令:如svn -h list -v
:
svn@svn-server:~/333/MyNote$ svn list -h -v
list (ls): List directory entries in the repository.
usage: list [TARGET[@REV]...]
List each TARGET file and the contents of each TARGET directory as
they exist in the repository. If TARGET is a working copy path, the
corresponding repository URL will be used. If specified, REV determines
in which revision the target is first looked up.
The default TARGET is '.', meaning the repository URL of the current
working directory.
Multiple --search patterns may be specified and the output will be
reduced to those paths whose last segment - i.e. the file or directory
name - matches at least one of these patterns.
With --verbose, the following fields will be shown for each item:
Revision number of the last commit
Author of the last commit
If locked, the letter 'O'. (Use 'svn info URL' to see details)
Size (in bytes)
Date and time of the last commit
Valid options:
-r [--revision] ARG : ARG (some commands also take ARG1:ARG2 range)
A revision argument can be one of:
NUMBER revision number
'{' DATE '}' revision at start of the date
'HEAD' latest in repository
'BASE' base rev of item's working copy
'COMMITTED' last commit at or before BASE
'PREV' revision just before COMMITTED
-v [--verbose] : print extra information
-R [--recursive] : descend recursively, same as --depth=infinity
-H [--human-readable] : with --verbose, show file sizes with base-2
unit suffixes (Byte, Kilobyte, Megabyte,
Gigabyte, Terabyte and Petabyte), limiting
the number of digits to three or less
--depth ARG : limit operation by depth ARG ('empty', 'files',
'immediates', or 'infinity')
--incremental : give output suitable for concatenation
--xml : output in XML
--include-externals : also operate on externals defined by
svn:externals properties
--search ARG : use ARG as search pattern (glob syntax, case-
and accent-insensitive, may require quotation marks
to prevent shell expansion)
Global options:
--username ARG : specify a username ARG
--password ARG : specify a password ARG (caution: on many operating
systems, other users will be able to see this)
--password-from-stdin : read password from stdin
--no-auth-cache : do not cache authentication tokens
--non-interactive : do no interactive prompting (default is to prompt
only if standard input is a terminal device)
--force-interactive : do interactive prompting even if standard input
is not a terminal device
--trust-server-cert : deprecated; same as
--trust-server-cert-failures=unknown-ca
--trust-server-cert-failures ARG : with --non-interactive, accept SSL server
certificates with failures; ARG is comma-separated
list of 'unknown-ca' (Unknown Authority),
'cn-mismatch' (Hostname mismatch), 'expired'
(Expired certificate), 'not-yet-valid' (Not yet
valid certificate) and 'other' (all other not
separately classified certificate errors).
--config-dir ARG : read user configuration files from directory ARG
--config-option ARG : set user configuration option in the format:
FILE:SECTION:OPTION=[VALUE]
For example:
servers:global:http-library=serf
其中-v参数使用来显示全局参数(global options)。
2. 向仓库中导入代码结构
使用 svn import FILE URL
:将代码结构导入到仓库中,svn import不需要工作副本也可以将代码导入到仓库。
在任意路径将新创建的项目目录project5导入到仓库指定仓库中:
svn@svn-server:~$ svn import project5/ svn://localhost/MyNote/project5
Log message unchanged or not specified
(a)bort, (c)ontinue, (e)dit:
c
Adding project5/aaa.c
Adding project5/branches
Adding project5/tags
Adding project5/trunk
Committing transaction...
Committed revision 11.
然后查看仓库中是否包含新添加的文件:
svn@svn-server:~/MyNote$ svn list
project1/
project2/
project3/
project4/
project5/
发现代码目录已经被正确的导入到了仓库中。
3. 从仓库中检出工作副本
使用 `svn checkout URL localdir*将仓库中的目录在用户主机创建一个该目录的工作副本,除非特意指定,否则这个仓库将包含仓库最新版本的数据:
svn@svn-server:~/111$ svn checkout svn://localhost/MyNote
A MyNote/project1
A MyNote/project1/branches
A MyNote/project1/tags
A MyNote/project1/trunk
A MyNote/project1/trunk/README.txt
A MyNote/project2
A MyNote/project2/branches
A MyNote/project2/tags
A MyNote/project2/trunk
...
localdir就是你希望checkout到的本地路径,如果路径不存在,会自动创建,如果为空,则使用仓库上的路径名。
svn可以检出任仓库下面任一目录,但是前提是当前用户必须有权限。通常checkout下来的工作副本(working copy),只是本地的一个普通文件夹,你可以对它执行任何操作,甚至删除整个目录。想要在仓库中删除复制或者移动文件,必须使用svn delete、svn copy、svn move而不是本地的删除复制移动,这个在后面会讲。
工作流
通常基本工作周期含有以下步骤:
- 更新工作副本:svn update(简写svn up)
- 修改:
- 添加(svn add)
- 删除(svn delete)
- 复制(svn copy)
- 移动(svn move)
- 审查修改:
svn status
和svn diff
- 撤销修改:svn revert
- 冲突合并:
- 首先执行svn update更新别人的修改到本地工作副本
- 如果含有冲突则手动解决冲突
- 然后svn resolve将工作副本标记为冲突解决完毕
1. 更新
所谓的更新就是从远程仓库中获取最新版本的代码和版本号。
如果同时有多人在修改相同的模块,就需要用户提交前更新自己的工作副本,以获取最新版本的代码。
svn不允许用户像过时的版本提交代码,执行update的时候也会将版本号更新到最新。
svn@svn-server:~/111/MyNote/project3/trunk$ svn up
Updating '.':
At revision 11.
2. 修改
修改分为两种:文件修改和目录修改,修改文件的时候可以使用任意编辑器进行修改,但是修改目录结构如添加删除文件,复制文件和目录都要使用svn自带的命令完成。
svn add
:添加文件
svn@svn-server:~/MyNote/project3/trunk$ svn add foo.c
A foo.c
svn@svn-server:~/MyNote/project3/trunk$ svn commit -m "add foo.c"
Adding foo.c
Transmitting file data .done
Committing transaction...
Committed revision 12.
svn@svn-server:~/MyNote/project3/trunk$ svn list ^/project3/trunk
foo.c
如果添加的是一个目录,svn会将目录中所有文件都添加到仓库中;如果想只添加目录本身,则要带上选项–depth=empth
svn delete
:删除文件
svn@svn-server:~/111/MyNote/project3/trunk$ svn delete foo.c
D foo.c
svn@svn-server:~/111/MyNote/project3/trunk$ svn commit -m "delete foo.c"
Deleting foo.c
Committing transaction...
Committed revision 13.
svn@svn-server:~/111/MyNote/project3/trunk$ svn list ^/project3/trunk
可以看到上面添加的foo.c已经被删除了。
svn mkdir:创建目录
svn mkdir FOO 等价于:mkdir FOO; svn add FOO
svn copy:复制文件
svn copy FOO BAR
从FOO复制出一个BAR,并把BAR添加到需要进行版本控制的名单中。BAR被提交到仓库后。Subversion会记录它是由FOO复制得到的。除非带上选项--parents
,否则svn copy
不会创建父目录。
svn@svn-server:~/111/MyNote/project3/trunk$ svn mkdir FOO
A FOO
svn@svn-server:~/111/MyNote/project3/trunk$ svn copy FOO BAR
A BAR
svn@svn-server:~/111/MyNote/project3/trunk$ svn commit -m "mkdir FOO & copy to BAR"
Adding BAR
Adding FOO
Committing transaction...
Committed revision 14.
svn@svn-server:~/111/MyNote/project3/trunk$ svn list ^/project3/trunk
BAR/
FOO/
svn move:移动文件
等价于svn copy FOO BAR; svn delete FOO
svn@svn-server:~/111/MyNote/project3/trunk$ svn move FOO TOO
A TOO
D FOO
svn@svn-server:~/111/MyNote/project3/trunk$ svn commit -m " move FOO to TOO"
Deleting FOO
Adding TOO
Committing transaction...
Committed revision 15.
svn@svn-server:~/111/MyNote/project3/trunk$ svn list ^/project3/trunk
BAR/
TOO/
3. 审查修改
工作副本修改完毕之后,可以使用svn status查看修改整体概述或者svn diff查看修改细节。
下面我们添加一个文件foo.c
svn@svn-server:~/111/MyNote/project3/trunk$ cat foo.c
this is a new text foo.c
add by liujunming
然后将其提交到仓库中:
svn@svn-server:~/111/MyNote/project3/trunk$ svn commit -m "add foo.c"
Adding foo.c
Transmitting file data .done
Committing transaction...
Committed revision 16.
然后我们添加一行:
svn@svn-server:~/111/MyNote/project3/trunk$ cat foo.c
this is a new text foo.c
add by liujunming
add a new line.
然后使用***svn status ***查看文件状态:
svn@svn-server:~/111/MyNote/project3/trunk$ svn status
M foo.c
M表示文件被修改。
使用***svn diff***查看修改详情:
svn@svn-server:~/111/MyNote/project3/trunk$ svn diff foo.c
Index: foo.c
===================================================================
--- foo.c (revision 16)
+++ foo.c (working copy)
@@ -1,2 +1,3 @@
this is a new text foo.c
add by liujunming
+add a new line.
可以看到第三行为新添加的。
将我们的修改提交再查看:发现工作区已经没有修改了,因为最新版本就是我们的上一次提交。
svn@svn-server:~/111/MyNote/project3/trunk$ svn commit -m "add new line"
Sending foo.c
Transmitting file data .done
Committing transaction...
Committed revision 17.
svn@svn-server:~/111/MyNote/project3/trunk$ svn status
svn@svn-server:~/111/MyNote/project3/trunk$ svn diff foo.c
3.1 svn status状态说明
- ? item
- 文件、目录或者符号链接item不在版本控制名单中。
- A item
- 文件、目录或者符号连接item是新增的,在下一次commit的时候会加入到仓库中。
- C item
- 文件item有为解决的冲突,即更新下来的文件和有相同的修改区域,用户必须解决掉冲突之后才能继续向仓库提交修改。
- D item
- 文件、目录或者符号连接item已经被删除(指的是svn delete)在下一次commit的时候会从仓库中删除item。
- M item
- 文件item的内容被修改
3.2 svn diff输出说明
- 新增行用 “+” 标注;
- 删除行用 ”-“ 标注;
3.3 使用外部差别比较工具
svn diff --diff-cmd /usr/bin/diff -x “-i” foo.c
4 撤销修改
svn@svn-server:~/MyNote/project5$ svn status
M aaa.c
svn@svn-server:~/MyNote/project5$ svn revert aaa.c
Reverted 'aaa.c'
svn@svn-server:~/MyNote/project5$ svn status
svn@svn-server:~/MyNote/project5$
5 冲突解决
TODO:
添加流程图
5.1 冲突产生的原因
什么时候会发生冲突?假设A和B同时修改了foo.c文件的同一行,A先提交,然后B在update的时候就会报冲突。
5.2 举例说明
假设仓库最新版本号为18现在有一个foo.c文件,内容如下:
svn@svn-server:~/MyNote/project3/trunk$ cat foo.c
first line add
second line add
third line add
A和B都update仓库的18版本的代码,进行修改。
A首先修改了foo.c第二行,并且提交,提交之后版本号变成了19:
svn@svn-server:~/MyNote/project3/trunk$ cat foo.c
first line add
second line add A modify
third line add
svn@svn-server:~/MyNote/project3/trunk$ svn status
M foo.c
svn@svn-server:~/MyNote/project3/trunk$ svn commit -m "modify the second line"
Sending foo.c
Transmitting file data .done
Committing transaction...
Committed revision 19.
此时B也修改完了代码,在提交代码前执行update,准备合并仓库新版本的代码后再提交:
svn@svn-server:~/MyNote/project3/trunk$ cat foo.c
first line add
second line add B modify
third line add
svn@svn-server:~/MyNote/project3/trunk$ svn update
Updating '.':
C foo.c
Updated to revision 19.
Summary of conflicts:
Text conflicts: 1
Merge conflict discovered in file 'foo.c'.
Select: (p) Postpone, (df) Show diff, (e) Edit file, (m) Merge,
(s) Show all options:
在B执行update的时候发现,A和他同时修改了foo.c相同代码行,造成冲突,于是B根据df提示查看冲突:
Select: (p) Postpone, (df) Show diff, (e) Edit file, (m) Merge,
(s) Show all options: df
--- foo.c.r19 - THEIRS
+++ foo.c - MERGED
@@ -1,3 +1,9 @@
first line add
+<<<<<<< .mine
+second line add B modify
+||||||| .r18
+second line add
+=======
second line add A modify
+>>>>>>> .r19
third line add
根据df输出,可以看到:A和B同时基于18版本修改了相同行,因此产生冲突
查看update后的文件状态:
5.3 冲突合并的方法
使用命令行合并冲突的方法有以下几种方式:
- 撤销->更新->修改->提交:
- 先备份foo.c保留我们的修改记录
- 然后revert foo.c,将我们的修改全部撤销,还原成没有修改的时候
- 执行update,将A提交的代码更新下来
- 将我们备份的修改,手动合并到新版本的foo.c中
- 提交版本
- 使用自带的合并工具
- svn resolve foo.c
- 输入m进行合并
- 输入r,将合并结果标记为resolved
- 提交
svn@svn-server:~/MyNote/project3/trunk$ svn resolve foo.c
Merge conflict discovered in file 'foo.c'.
Select: (p) Postpone, (df) Show diff, (e) Edit file, (m) Merge,
(s) Show all options: m
Merging 'foo.c'.
Conflicting section found during merge:
(1) their version (at line 2) |(2) your version (at line 2)
---------------------------------------------------------+---------------------------------------------------------
second line add A modify |second line add B modify
---------------------------------------------------------+---------------------------------------------------------
Select: (1) use their version, (2) use your version,
(12) their version first, then yours,
(21) your version first, then theirs,
(e1) edit their version and use the result,
(e2) edit your version and use the result,
(eb) edit both versions and use the result,
(p) postpone this conflicting section leaving conflict markers,
(a) abort file merge and return to main menu:
- 直接手动编辑修改
- 手动合并代码
- svn resolve foo.c,等同与上面r,将冲突标记为解决
- 提交代码
svn@svn-server:~/MyNote/project3/trunk$ cat foo.c
first line add
second line add A modify
second line add B modify
third line add
svn@svn-server:~/MyNote/project3/trunk$ svn status
C foo.c
? foo.c.mine
? foo.c.r18
? foo.c.r19
svn@svn-server:~/MyNote/project3/trunk$ svn resolved foo.c
Resolved conflicted state of 'foo.c'
svn@svn-server:~/MyNote/project3/trunk$ svn status foo.c
M foo.c
svn@svn-server:~/MyNote/project3/trunk$ svn commit foo.c -m "resolved conflict"
Sending foo.c
Transmitting file data .done
Committing transaction...
Committed revision 20.
6. 提交修改
同时提交多个文件多个修改,要么全部成功,要么全部失败。
不可以过时的版本号提交修改,因此提交前必须update。
7. 处理目录冲突
旧版本目录冲突需要手动解决,但是在验证的时候发现新版本的svn已经可以自动合并目录冲突了。
假如A和B同时update了21版本的trunk,此时A修改bar.c为baz.c并且提交到新版本22中:
svn@svn-server:~/MyNote/project3/trunk$ svn mv bar.c brz.c
A brz.c
D bar.c
svn@svn-server:~/MyNote/project3/trunk$ svn commit -m "rename bar.c to brz.c"
Deleting bar.c
Adding brz.c
Sending foo.c
Transmitting file data .done
Committing transaction...
Committed revision 22.
此时B也修改了bar.c,并且准备提交:
vn@svn-server:~/111/MyNote/project3/trunk$ cat bar.c
B modify, add a new line
svn@svn-server:~/111/MyNote/project3/trunk$ svn commit -m "B added a new line"
Sending bar.c
Transmitting file data .done
Committing transaction...
svn: E160013: Commit failed (details follow):
svn: E160013: File not found: transaction '22-o', path '/project3/trunk/bar.c'
发现冲突后,B执行update
svn@svn-server:~/111/MyNote/project3/trunk$ svn up
Updating '.':
C bar.c
A brz.c
U foo.c
Updated to revision 22.
Summary of conflicts:
Tree conflicts: 1
Searching tree conflict details for 'bar.c' in repository:
Checking r22... done
Tree conflict on 'bar.c':
File updated from r21 to r22 was moved to '^/project3/trunk/brz.c' by admin in r22.
A file containing uncommitted changes was found in the working copy.
Applying recommended resolution 'Move and merge':
G brz.c
Tree conflict at 'bar.c' marked as resolved.
Summary of conflicts:
Tree conflicts: 0 remaining (and 1 already resolved)
查看发现bar.c已经被自动删除,修改合并到了brz.c中了,此时我们直接提交即可。
svn@svn-server:~/111/MyNote/project3/trunk$ lt
total 16
drwxrwxr-x 2 svn svn 4096 Sep 13 13:03 TOO
drwxrwxr-x 2 svn svn 4096 Sep 13 13:03 BAR
-rw-rw-r-- 1 svn svn 100 Sep 18 10:05 foo.c
-rw-rw-r-- 1 svn svn 25 Sep 18 10:05 brz.c
svn@svn-server:~/111/MyNote/project3/trunk$ cat brz.c
B modify, add a new line
svn@svn-server:~/111/MyNote/project3/trunk$ svn status
M brz.c
svn@svn-server:~/111/MyNote/project3/trunk$ svn commit -m "B add a new line"
Sending brz.c
Transmitting file data .done
Committing transaction...
Committed revision 23.
检查历史
SvbVersion允许用户查看文件的历史版本,用户可以使用命令查看任意一个时间点或者版本号的版本
下面列举几个检索历史数据的命令:
- svn diff:
- 从行级别查看修改内容。
- svn log:
- 和版本号绑定的日志消息,以及作者,日期,还有路径。
- svn cat:
- 指定版本的文件内容。
- svn annotate:
- 根据给定的版本号,查看该版本下的文件的每一行的最后一次修改信息。
- svn list:
- 列出指定版本下文件和目录清单。
1. 比较历史修订细节
svn diff有三种用法:
- 查看本地修改。
直接使用svn diff不加选项,就会拿文件的当前内容和存放在.svn中的原始文件做对比:
svn@svn-server:~/MyNote/project3/trunk$ cat foo.c
first line add
second line add A modify
second line add B modify
modify for svn diff
third line add
svn@svn-server:~/MyNote/project3/trunk$ svn diff foo.c
Index: foo.c
===================================================================
--- foo.c (revision 21)
+++ foo.c (working copy)
@@ -1,4 +1,5 @@
first line add
second line add A modify
second line add B modify
+modify for svn diff
third line add
- 比较工作副本和仓库中指定版本。
如果选项带上–reversion(-r),命令就会把工作副本和仓库指定的版本号做对比:
svn@svn-server:~/MyNote/project3/trunk$ svn diff foo.c -r18
Index: foo.c
===================================================================
--- foo.c (revision 18)
+++ foo.c (working copy)
@@ -1,3 +1,5 @@
first line add
-second line add
+second line add A modify
+second line add B modify
+modify for svn diff
third line add
- 比较仓库的历史版本之间区别
使用 --rversion(-r),传递一对用冒号隔开的版本号,就会比较两个版本之间的差异:
svn@svn-server:~/MyNote/project3/trunk$ svn diff foo.c -r18:20
Index: foo.c
===================================================================
--- foo.c (revision 18)
+++ foo.c (revision 20)
@@ -1,3 +1,4 @@
first line add
-second line add
+second line add A modify
+second line add B modify
third line add
使用 --change(-c) 版本号
比较指定版本和前一个版本的差别:
svn@svn-server:~/MyNote/project3/trunk$ svn diff foo.c -c 19
Index: foo.c
===================================================================
--- foo.c (revision 18)
+++ foo.c (revision 19)
@@ -1,3 +1,3 @@
first line add
-second line add
+second line add A modify
third line add
- 如果没有工作副本,
svn diff
也可以比较仓库中版本之间的区别,指定URL即可:
svn@svn-server:/svn_repos/MyNote/conf$ svn diff -c 19 svn://localhost/MyNote/project3/trunk/foo.c
Index: foo.c
===================================================================
--- foo.c (revision 18)
+++ foo.c (revision 19)
@@ -1,3 +1,3 @@
first line add
-second line add
+second line add A modify
third line add
2. 查看历史修改信息
可以使用svn log
查看历史修改信息,显示的信息包含修改的作者,版本号,时间和日期,以及日志消息。
svn@svn-server:~/MyNote/project3/trunk$ svn log
------------------------------------------------------------------------
r21 | admin | 2021-09-18 07:10:25 +0000 (Sat, 18 Sep 2021) | 1 line
add bar.c
------------------------------------------------------------------------
r20 | admin | 2021-09-18 06:53:35 +0000 (Sat, 18 Sep 2021) | 1 line
resolved conflict
------------------------------------------------------------------------
r19 | admin | 2021-09-18 06:05:30 +0000 (Sat, 18 Sep 2021) | 1 line
modify the second line
------------------------------------------------------------------------
r18 | admin | 2021-09-16 12:31:50 +0000 (Thu, 16 Sep 2021) | 1 line
modify foo.c
------------------------------------------------------------------------
r17 | admin | 2021-09-13 13:27:50 +0000 (Mon, 13 Sep 2021) | 1 line
add new line
...
如果想要查看指定版本区间的日志,或者是单个版本号的日志,又或者是改变打印顺序,就带上选项--revision(-r)
:
命令 | 描述 |
---|---|
svn log -r 18:20 | 按照时间顺序打印从版本号18到20的日志 |
svn log -r 20:18 | 按照时间逆序打印从版本号18到20的日志 |
svn log -r 18 | 显示版本号18的日志 |
svn@svn-server:~/MyNote/project3/trunk$ svn log -r 18:21
Authentication realm: <svn://localhost:3690> 9b638b28-bcc8-4373-9064-37864bc908fc
------------------------------------------------------------------------
r18 | admin | 2021-09-16 12:31:50 +0000 (Thu, 16 Sep 2021) | 1 line
modify foo.c
------------------------------------------------------------------------
r19 | admin | 2021-09-18 06:05:30 +0000 (Sat, 18 Sep 2021) | 1 line
modify the second line
------------------------------------------------------------------------
r20 | admin | 2021-09-18 06:53:35 +0000 (Sat, 18 Sep 2021) | 1 line
resolved conflict
------------------------------------------------------------------------
r21 | admin | 2021-09-18 07:10:25 +0000 (Sat, 18 Sep 2021) | 1 line
add bar.c
------------------------------------------------------------------------
也可以查看单个文件的日志:
svn@svn-server:~/MyNote/project3/trunk$ svn log bar.c
Authentication realm: <svn://localhost:3690> 9b638b28-bcc8-4373-9064-37864bc908fc
------------------------------------------------------------------------
r21 | admin | 2021-09-18 07:10:25 +0000 (Sat, 18 Sep 2021) | 1 line
add bar.c
------------------------------------------------------------------------
可以使用svn log --verbose(-v)
在日志输出中显示每个版本受影响的文件和路径
svn@svn-server:~/MyNote/project3/trunk$ svn log foo.c -r19
------------------------------------------------------------------------
r19 | admin | 2021-09-18 06:05:30 +0000 (Sat, 18 Sep 2021) | 1 line
modify the second line
------------------------------------------------------------------------
svn@svn-server:~/MyNote/project3/trunk$ svn log foo.c -r19 -v
------------------------------------------------------------------------
r19 | admin | 2021-09-18 06:05:30 +0000 (Sat, 18 Sep 2021) | 1 line
Changed paths:
M /project3/trunk/foo.c
modify the second line
也可以使用 svn log -q
阻止打印消息主体:
svn@svn-server:~/MyNote/project3/trunk$ svn log -q
------------------------------------------------------------------------
r21 | admin | 2021-09-18 07:10:25 +0000 (Sat, 18 Sep 2021)
------------------------------------------------------------------------
r20 | admin | 2021-09-18 06:53:35 +0000 (Sat, 18 Sep 2021)
------------------------------------------------------------------------
r19 | admin | 2021-09-18 06:05:30 +0000 (Sat, 18 Sep 2021)
------------------------------------------------------------------------
r18 | admin | 2021-09-16 12:31:50 +0000 (Thu, 16 Sep 2021)
------------------------------------------------------------------------
r17 | admin | 2021-09-13 13:27:50 +0000 (Mon, 13 Sep 2021)
------------------------------------------------------------------------
r16 | admin | 2021-09-13 13:23:04 +0000 (Mon, 13 Sep 2021)
------------------------------------------------------------------------
r15 | admin | 2021-09-13 13:08:43 +0000 (Mon, 13 Sep 2021)
------------------------------------------------------------------------
r14 | admin | 2021-09-13 13:03:33 +0000 (Mon, 13 Sep 2021)
------------------------------------------------------------------------
r13 | admin | 2021-09-13 12:46:24 +0000 (Mon, 13 Sep 2021)
------------------------------------------------------------------------
r12 | admin | 2021-09-13 12:29:08 +0000 (Mon, 13 Sep 2021)
------------------------------------------------------------------------
r1 | admin | 2021-07-31 02:54:34 +0000 (Sat, 31 Jul 2021)
如果同时使用-q和-v那么就只会打印被修改的文件路径:
svn@svn-server:~/MyNote/project3/trunk$ svn log -q -v
------------------------------------------------------------------------
r21 | admin | 2021-09-18 07:10:25 +0000 (Sat, 18 Sep 2021)
Changed paths:
A /project3/trunk/bar.c
------------------------------------------------------------------------
r20 | admin | 2021-09-18 06:53:35 +0000 (Sat, 18 Sep 2021)
Changed paths:
M /project3/trunk/foo.c
------------------------------------------------------------------------
r19 | admin | 2021-09-18 06:05:30 +0000 (Sat, 18 Sep 2021)
Changed paths:
M /project3/trunk/foo.c
------------------------------------------------------------------------
r18 | admin | 2021-09-16 12:31:50 +0000 (Thu, 16 Sep 2021)
Changed paths:
R /project3/trunk/foo.c (from /project3/trunk/foo.c:12)
------------------------------------------------------------------------
r17 | admin | 2021-09-13 13:27:50 +0000 (Mon, 13 Sep 2021)
Changed paths:
M /project3/trunk/foo.c
3. 浏览仓库
3.1 显示文件内容
使用svn cat
显示仓库内容。
查看仓库中foo.c文件在19版本的内容:
svn@svn-server:~/MyNote/project3/trunk$ svn cat foo.c -r19
first line add
second line add A modify
third line add
3.2 显示每一行的修改属性
使用***svn annotate***输出文件内容和每一行最后一次被修改时的作者、如果使用了***–verbose(-v)***还会显示版本号及其日期。
svn@svn-server:~/MyNote/project3/trunk$ svn annotate foo.c -v
18 admin 2021-09-16 12:31:50 +0000 (Thu, 16 Sep 2021) first line add
19 admin 2021-09-18 06:05:30 +0000 (Sat, 18 Sep 2021) second line add A modify
20 admin 2021-09-18 06:53:35 +0000 (Sat, 18 Sep 2021) second line add B modify
- - - modify for svn diff
18 admin 2021-09-16 12:31:50 +0000 (Thu, 16 Sep 2021) third line add
其中第四行的属性展示不出来,因为在工作副本中被我们修改了,使用***svn annotate foo.c@BASE***查看没有被修改的foo.c:
svn@svn-server:~/MyNote/project3/trunk$ svn annotate foo.c@BASE
18 admin first line add
19 admin second line add A modify
20 admin second line add B modify
18 admin third line add
3.3 获取仓库快照
使用***svn update --reversion(-r)版本号***将工作副本更新到指定版本:
svn@svn-server:~/MyNote/project3/trunk$ cat foo.c
first line add
second line add A modify
second line add B modify
modify for svn diff
third line add
svn@svn-server:~/MyNote/project3/trunk$ svn up -r18
Updating '.':
D bar.c
G foo.c
Updated to revision 18.
svn@svn-server:~/MyNote/project3/trunk$ cat foo.c
first line add
second line add
modify for svn diff
third line add
检出指定版本:
svn@svn-server:~/222$ svn checkout svn://localhost/MyNote@19
A MyNote/project1
A MyNote/project1/branches
A MyNote/project1/tags
A MyNote/project1/trunk
A MyNote/project1/trunk/README.txt
A MyNote/project2
A MyNote/project2/branches
A MyNote/project2/tags
A MyNote/project2/trunk
A MyNote/project3
A MyNote/project3/branches
A MyNote/project3/tags
A MyNote/project3/trunk
A MyNote/project3/trunk/BAR
A MyNote/project3/trunk/TOO
A MyNote/project3/trunk/foo.c
A MyNote/project4
A MyNote/project4/branches
A MyNote/project4/tags
A MyNote/project4/trunk
A MyNote/project5
A MyNote/project5/aaa.c
A MyNote/project5/branches
A MyNote/project5/tags
A MyNote/project5/trunk
Checked out revision 19.
如果用户向构建一个发布版,其中包含了所有的被版本控制的文件和目录,可以使用***svn export***创建仓库副本(不包含.svn)目录,命令语法和svn checkout相同
A MyNote-19
A MyNote-19/project1
A MyNote-19/project1/branches
A MyNote-19/project1/tags
A MyNote-19/project1/trunk
A MyNote-19/project1/trunk/README.txt
A MyNote-19/project2
A MyNote-19/project2/branches
A MyNote-19/project2/tags
A MyNote-19/project2/trunk
A MyNote-19/project3
A MyNote-19/project3/branches
A MyNote-19/project3/tags
A MyNote-19/project3/trunk
A MyNote-19/project3/trunk/BAR
A MyNote-19/project3/trunk/TOO
A MyNote-19/project3/trunk/foo.c
A MyNote-19/project4
A MyNote-19/project4/branches
A MyNote-19/project4/tags
A MyNote-19/project4/trunk
A MyNote-19/project5
A MyNote-19/project5/aaa.c
A MyNote-19/project5/branches
A MyNote-19/project5/tags
A MyNote-19/project5/trunk
Exported revision 19.
svn@svn-server:~/222$ lt
total 8
drwxrwxr-x 8 svn svn 4096 Sep 18 09:10 MyNote
drwxrwxr-x 7 svn svn 4096 Sep 18 09:15 MyNote-19
3.4 版本回退
分支管理
仓库管理
1. 仓库部署策略
- 单个仓库多个项目:
- 单个仓库单个项目
2.
版本号拓展
版本号关键字
- HEAD:仓库中最新的版本号。
- BASE:工作副本update的版本号。
svn@svn-server:~/MyNote/project3/trunk$ svn log -r BASE
------------------------------------------------------------------------
r21 | admin | 2021-09-18 07:10:25 +0000 (Sat, 18 Sep 2021) | 1 line
add bar.c
------------------------------------------------------------------------
svn@svn-server:~/MyNote/project3/trunk$ svn up
Updating '.':
U brz.c
Updated to revision 23.
svn@svn-server:~/MyNote/project3/trunk$ svn log -r BASE
------------------------------------------------------------------------
r23 | admin | 2021-09-18 10:10:10 +0000 (Sat, 18 Sep 2021) | 1 line
B add a new line
------------------------------------------------------------------------
- COMMITTED:工作副本中某个文件的最近提交版本号。
- PREV:工作副本中某个文件的最后一次提交版本号的前一个版本号,其实就是COMMITTED - 1。
svn@svn-server:~/MyNote/project3/trunk$ svn diff -r COMMITTED:PREV foo.c
Index: foo.c
===================================================================
--- foo.c (revision 22)
+++ foo.c (revision 21)
@@ -1,5 +1,4 @@
first line add
second line add A modify
second line add B modify
-modify for svn diff
third line add
版本号日期
–rversion(-r)的参数还可以是日期,不过日期必须用{}括起来。SubVersion接受标准的ISO-8601格式的日期与时间,以及其它一些形式,下面是一些例子:
$ svn update -r {2006-02-17}
$ svn update -r {15:30}
$ svn update -r {15:30:00.200000}
$ svn update -r {"2006-02-17 15:30"}
$ svn update -r {"2006-02-17 15:30 +0230"}
$ svn update -r {2006-02-17T15:30}
$ svn update -r {2006-02-17T15:30Z}
$ svn update -r {2006-02-17T15:30-04:00}
$ svn update -r {20060217T1530}
$ svn update -r {20060217T1530Z}
$ svn update -r {20060217T1530-0500}
-r {日期}理解为,日期前,比如2006-02-17旧理解为17号之前,但是不包含17号。
//TODO:
为每一个操作提供小乌龟演示:
整理一套svn服务器搭建配置流程:
添加svn配置文件说明:
添加svn常见问题以及解决办法:
svnhook脚本详细介绍:
简单介绍git,git和svn区别