一. SVN 常见属于和文件状态
1. 常见术语
-
版本根目录
上篇博客中用到的/application/svndata
-
版本库
repositoty 在服务器端保存着的项目中所有的文件和操作记录,一般一个项目对应一个版本库
-
版本
Revision 版本库中任意一次改动对应一个版本。
-
版本号
版本库每次接受到提交操作后,会保存数据,并将版本库的版本号+1
-
检出
客户端第一次从版本库中下载项目,当前目录下保存——创建工作目录。
-
工作副本
在客户端保存着的当前项目文件的目录(可能与版本库内容不一致)。
-
更新
客户端从版本库下载最新版的项目文件,并更新版本号
-
提交
将工作副本中更改后的项目提交的版本库
2. 文件状态
文件状态是文件对于工作副本而言的,不是对于SVN 服务器版本库。
-
无版本控制
在工作副本中新增的文件,这个时候这个文件是无版本控制状态
-
增加
在共组副本中将无版本控制状态的文件,添加到版本控制系统中
-
修改
在工作副本中修改了文件
-
常规
本地工作副本中的数据和svn 服务器版本库中的数据一致的状态
二. SVN 命令的使用
1. 查看 svn 命令帮助
[root@Python ~]# svn --help
usage: svn <subcommand> [options] [args]
Subversion command-line client, version 1.6.11.
Type 'svn help <subcommand>' for help on a specific subcommand.
Type 'svn --version' to see the program version and RA modules
or '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
blame (praise, annotate, ann)
cat
changelist (cl)
checkout (co)
cleanup
commit (ci)
copy (cp)
delete (del, remove, rm)
diff (di)
export
help (?, h)
import
info
list (ls)
lock
log
merge
mergeinfo
mkdir
move (mv, rename, ren)
propdel (pdel, pd)
propedit (pedit, pe)
propget (pget, pg)
proplist (plist, pl)
propset (pset, ps)
resolve
resolved
revert
status (stat, st)
switch (sw)
unlock
update (up)
Subversion is a tool for version control.
For additional information, see http://subversion.tigris.org/
[root@Python ~]# svn --help
usage: svn <subcommand> [options] [args]
Subversion command-line client, version 1.6.11.
Type 'svn help <subcommand>' for help on a specific subcommand.
Type 'svn --version' to see the program version and RA modules
or '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
blame (praise, annotate, ann)
cat
changelist (cl)
checkout (co)
cleanup
commit (ci)
copy (cp)
delete (del, remove, rm)
diff (di)
export
help (?, h)
import
info
list (ls)
lock
log
merge
mergeinfo
mkdir
move (mv, rename, ren)
propdel (pdel, pd)
propedit (pedit, pe)
propget (pget, pg)
proplist (plist, pl)
propset (pset, ps)
resolve
resolved
revert
status (stat, st)
switch (sw)
unlock
update (up)
Subversion is a tool for version control.
For additional information, see http://subversion.tigris.org/
[root@Python ~]# svn info --help
info: Display information about a local or remote item.
usage: info [TARGET[@REV]...]
Print information about each TARGET (default: '.').
TARGET may be either a working-copy path or URL. If specified, REV
determines in which revision the target is first looked up.
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
-R [--recursive] : descend recursively, same as --depth=infinity
--depth ARG : limit operation by depth ARG ('empty', 'files',
'immediates', or 'infinity')
--targets ARG : pass contents of file ARG as additional args
--incremental : give output suitable for concatenation
--xml : output in XML
--changelist ARG : operate only on members of changelist ARG
[aliases: --cl]
Global options:
--username ARG : specify a username ARG
--password ARG : specify a password ARG
--no-auth-cache : do not cache authentication tokens
--non-interactive : do no interactive prompting
--trust-server-cert : accept unknown SSL server certificates without
prompting (but only with '--non-interactive')
--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
[root@Python ~]# svn info svn://192.168.10.1/sadoc
Path: sadoc
URL: svn://192.168.10.1/sadoc
Repository Root: svn://192.168.10.1/sadoc
Repository UUID: 1aa20afc-4318-4497-a077-c0f8c47884c4
Revision: 3
Node Kind: directory
Last Changed Author: admin
Last Changed Rev: 3
Last Changed Date: 2017-12-14 00:38:24 +0800 (Thu, 14 Dec 2017)
[root@Python ~]# svn info svn://192.168.10.1/sadoc -r 2
Path: sadoc
URL: svn://192.168.10.1/sadoc
Repository Root: svn://192.168.10.1/sadoc
Repository UUID: 1aa20afc-4318-4497-a077-c0f8c47884c4
Revision: 2
Node Kind: directory
Last Changed Author: admin
Last Changed Rev: 2
Last Changed Date: 2017-12-14 00:38:08 +0800 (Thu, 14 Dec 2017)
2. 导入 svn 原始目录树
svn import [PATH] URL -m "注释信息"
注意:svn import 命令必须接 -m 带注释信息
将项目导入到 svn 版本库中管理
[root@Python ~]# svn import --help
import: Commit an unversioned file or tree into the repository.
# 将未版本化的文件或树提交到存储库中。
usage: import [PATH] URL
Recursively commit a copy of PATH to URL.
If PATH is omitted '.' is assumed.
Parent directories are created as necessary in the repository.
If PATH is a directory, the contents of the directory are added
directly under URL.
Unversionable items such as device files and pipes are ignored
if --force is specified.
Valid options:
-q [--quiet] : print nothing, or only summary information
-N [--non-recursive] : obsolete; try --depth=files or --depth=immediates
# 表示不递归,则只导入该目录下的文件,且不导入目录
--depth ARG : limit operation by depth ARG ('empty', 'files',
'immediates', or 'infinity')
--auto-props : enable automatic properties
--force : force operation to run
--no-auto-props : disable automatic properties
-m [--message] ARG : specify log message ARG # 添加注释信息
-F [--file] ARG : read log message from file ARG
--force-log : force validity of log message source
--editor-cmd ARG : use ARG as external editor
--encoding ARG : treat value as being in charset encoding ARG
--with-revprop ARG : set revision property ARG in new revision
using the name[=value] format
--no-ignore : disregard default and svn:ignore property ignores
Global options:
--username ARG : specify a username ARG
--password ARG : specify a password ARG
--no-auth-cache : do not cache authentication tokens
--non-interactive : do no interactive prompting
--trust-server-cert : accept unknown SSL server certificates without
prompting (but only with '--non-interactive')
--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
要使用 svn 管理的软件项目通常会建3个目录:
[root@Node1 ~]# mkdir -pv /data/oldboy/{trunk,branch,tags}
mkdir: created directory `/data/oldboy'
mkdir: created directory `/data/oldboy/trunk' # 主干
mkdir: created directory `/data/oldboy/branch' # 分支
mkdir: created directory `/data/oldboy/tags' # 标签
[root@Node1 ~]# svn import /data/oldboy/ file:///application/svndata/sadoc -m "import svntree"
# 本地导入
Adding /data/oldboy/trunk
Adding /data/oldboy/branch
Adding /data/oldboy/tags
Committed revision 2.
或者:
[root@Node1 ~]# svn import /data/oldboy/ svn://192.168.10.1/sadoc -m "import svntree"
# 远程导入
Adding /data/oldboy/trunk
Adding /data/oldboy/branch
Adding /data/oldboy/tags
svn: File already exists: filesystem '/application/svndata/sadoc/db', transaction '2-2', path '/trunk'
3. svn checkout 和 svn export
3.1 svn checkout
checkout URL[@REV]... [PATH]
-r 指定版本参数
从版本库中检出工作副本
[root@Python ~]# svn checkout --help
checkout (co): Check out a working copy from a repository.
usage: checkout URL[@REV]... [PATH]
If specified, REV determines in which revision the URL is first
looked up.
If PATH is omitted, the basename of the URL will be used as
the destination. If multiple URLs are given each will be checked
out into a sub-directory of PATH, with the name of the sub-directory
being the basename of the URL.
If --force is used, unversioned obstructing paths in the working
copy destination do not automatically cause the check out to fail.
If the obstructing path is the same type (file or directory) as the
corresponding path in the repository it becomes versioned but its
contents are left 'as-is' in the working copy. This means that an
obstructing directory's unversioned children may also obstruct and
become versioned. For files, any content differences between the
obstruction and the repository are treated like a local modification
to the working copy. All properties from the repository are applied
to the obstructing path.
See also 'svn help update' for a list of possible characters
reporting the action taken.
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
-q [--quiet] : print nothing, or only summary information
-N [--non-recursive] : obsolete; try --depth=files or --depth=immediates
--depth ARG : limit operation by depth ARG ('empty', 'files',
'immediates', or 'infinity')
--force : force operation to run
--ignore-externals : ignore externals definitions
Global options:
--username ARG : specify a username ARG
--password ARG : specify a password ARG
--no-auth-cache : do not cache authentication tokens
--non-interactive : do no interactive prompting
--trust-server-cert : accept unknown SSL server certificates without
prompting (but only with '--non-interactive')
--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
[root@Python ~]# svn checkout svn://192.168.10.1/sadoc
A sadoc/trunk
A sadoc/V1
A sadoc/V1/1.txt
A sadoc/V2
A sadoc/v3
A sadoc/v5.txt
A sadoc/v6.txt
A sadoc/v7.log
A sadoc/branch
A sadoc/branch/v4
A sadoc/tags
Checked out revision 7.
注意: svn 命令默认会记住密码
3.2 svn export
export [-r REV] URL[@PEGREV] [PATH]
export [-r REV] PATH1[@PEGREV] [PATH2]
从版本库或工作副本导出数据
[root@Python ~]# svn export svn://192.168.10.1/sadoc test1
A test1
A test1/trunk
A test1/V1
A test1/V1/1.txt
A test1/V2
A test1/v3
A test1/v5.txt
A test1/v6.txt
A test1/v7.log
A test1/branch
A test1/branch/v4
A test1/tags
Exported revision 7.
[root@Python ~]# ls -a test1
. .. branch tags trunk V1 V2 v3 v5.txt v6.txt v7.log
[root@Python ~]# svn export test1 test2
svn: 'test1' is not a working copy
[root@Python ~]# svn export sadoc/ test2
Export complete.
[root@Python ~]# ls -a test2
. .. branch tags trunk V1 V2 v3 v5.txt v6.txt v7.log
3.3 总结
- checkout 和 export 用法一样
- checkout 检出的工作副本目录中包含.svn 文件夹是一个工作副本,而eport 不包含,只是单纯的导出项目文件,不是工作副本,无版本控制。
- .svn 记录着工作副本最后一次更新后的文件状态
- .svn 标记工作副本的一切变化
4. 查看 svn 服务器版本库中的数据和信息
4.1 list
list [TARGET[@REV]...]
-R 递归
列出版本库或工作副本处于版本控制中的所以文件。
[root@Python ~]# svn list svn://192.168.10.1/sadoc # 只能查看目录下的文件
V1/
V2/
branch/
tags/
trunk/
v3/
v5.txt
v6.txt
v7.log
[root@Python ~]# svn list svn://192.168.10.1/sadoc -v
7 admin Dec 14 00:56 ./
1 admin Dec 14 00:36 V1/
2 admin Dec 14 00:38 V2/
4 admin Dec 14 00:52 branch/
4 admin Dec 14 00:52 tags/
4 admin Dec 14 00:52 trunk/
3 admin Dec 14 00:38 v3/
5 admin 0 Dec 14 00:54 v5.txt
6 admin 0 Dec 14 00:55 v6.txt
7 admin 0 Dec 14 00:56 v7.log
[root@Python ~]# svn list sadoc -v
7 admin Dec 14 00:56 ./
1 admin Dec 14 00:36 V1/
2 admin Dec 14 00:38 V2/
4 admin Dec 14 00:52 branch/
4 admin Dec 14 00:52 tags/
4 admin Dec 14 00:52 trunk/
3 admin Dec 14 00:38 v3/
5 admin 0 Dec 14 00:54 v5.txt
6 admin 0 Dec 14 00:55 v6.txt
7 admin 0 Dec 14 00:56 v7.log
[root@Python ~]# svn list test1 -v
svn: 'test1' is not a working copy
[root@Python ~]# svn list -R sadoc/
V1/
V1/1.txt
V2/
V2/新建文件夹/
branch/
branch/v4
t1/
t1/t2/
t1/t2/t3/
t1/t2/t3/test.md
tags/
trunk/
v3/
v3/v8.log
v8/
v9/
v9/v9.log
新建文件夹/
新建文本文档 (2).txt
新建文本文档.txt
4.2 cat
cat TARGET[@REV]...
查看版本库或工作副本中的文件的内容。
[root@Python ~]# svn cat sadoc/V1/1.txt
V1
[root@Python ~]# svn cat svn://192.168.10.1/sadoc/V1/1.txt
V1
4.3 info
info [TARGET[@REV]...]
查看版本库或工作副本文件的详细信息
[root@Python sadoc]# svn info
Path: .
URL: svn://192.168.10.1/sadoc
Repository Root: svn://192.168.10.1/sadoc
Repository UUID: 1aa20afc-4318-4497-a077-c0f8c47884c4
Revision: 13
Node Kind: directory
Schedule: normal
Last Changed Author: xxj
Last Changed Rev: 13
Last Changed Date: 2017-12-14 02:18:14 +0800 (Thu, 14 Dec 2017)
[root@Python sadoc]# svn info /root/sadoc/
Path: /root/sadoc
URL: svn://192.168.10.1/sadoc
Repository Root: svn://192.168.10.1/sadoc
Repository UUID: 1aa20afc-4318-4497-a077-c0f8c47884c4
Revision: 13
Node Kind: directory
Schedule: normal
Last Changed Author: xxj
Last Changed Rev: 13
Last Changed Date: 2017-12-14 02:18:14 +0800 (Thu, 14 Dec 2017)
[root@Python sadoc]# svn info v3/v8.log
Path: v3/v8.log
Name: v8.log
URL: svn://192.168.10.1/sadoc/v3/v8.log
Repository Root: svn://192.168.10.1/sadoc
Repository UUID: 1aa20afc-4318-4497-a077-c0f8c47884c4
Revision: 35
Node Kind: file
Schedule: normal
Last Changed Author: admin
Last Changed Rev: 35
Last Changed Date: 2017-12-14 22:57:00 +0800 (Thu, 14 Dec 2017)
Text Last Updated: 2017-12-15 00:19:25 +0800 (Fri, 15 Dec 2017)
Checksum: d657c8dd2bf8f8497e315d72a75874eb
[root@Python sadoc]# svn info v3
Path: v3
URL: svn://192.168.10.1/sadoc/v3
Repository Root: svn://192.168.10.1/sadoc
Repository UUID: 1aa20afc-4318-4497-a077-c0f8c47884c4
Revision: 35
Node Kind: directory
Schedule: normal
Last Changed Author: admin
Last Changed Rev: 35
Last Changed Date: 2017-12-14 22:57:00 +0800 (Thu, 14 Dec 2017)
[root@Python sadoc]# svn info svn://192.168.10.1/sadoc/v3
Path: v3
URL: svn://192.168.10.1/sadoc/v3
Repository Root: svn://192.168.10.1/sadoc
Repository UUID: 1aa20afc-4318-4497-a077-c0f8c47884c4
Revision: 35
Node Kind: directory
Last Changed Author: admin
Last Changed Rev: 35
Last Changed Date: 2017-12-14 22:57:00 +0800 (Thu, 14 Dec 2017)
4.4 status
status [PATH...]
列出工作副本中的文件的状态
[root@Python ~]# svn status --help
status (stat, st): Print the status of working copy files and directories.
usage: status [PATH...]
' ' no modifications # 正常
'A' Added # 已被标记增加到版本控制中
'C' Conflicted # 文件存在冲突
'D' Deleted # 已被标记从版本库中删除
'I' Ignored # 忽略
'M' Modified # 已被更改过
'R' Replaced # 文件被替换
'X' an unversioned directory created by an externals definition
'?' item is not under version control # 无版本控制
'!' item is missing (removed by non-svn command) or incomplete # 文件缺失
'~' versioned item obstructed by some item of a different kind
4.5 log
查看工作副本或版本库提交日志(来自svn ci的-m参数)
[root@Python sadoc]# svn log --help
log: Show the log messages for a set of revision(s) and/or file(s).
usage: 1. log [PATH]
2. log URL[@REV] [PATH...]
Examples:
svn log
svn log foo.c
svn log http://www.example.com/repo/project/foo.c
svn log http://www.example.com/repo/project foo.c bar.c
[root@Python sadoc]# svn log
------------------------------------------------------------------------
r35 | admin | 2017-12-14 22:57:00 +0800 (Thu, 14 Dec 2017) | 1 line
------------------------------------------------------------------------
r34 | xxj | 2017-12-14 22:38:13 +0800 (Thu, 14 Dec 2017) | 1 line
------------------------------------------------------------------------
[root@Python sadoc]# svn log svn://192.168.10.1/sadoc/v3
------------------------------------------------------------------------
r35 | admin | 2017-12-14 22:57:00 +0800 (Thu, 14 Dec 2017) | 1 line
------------------------------------------------------------------------
r34 | xxj | 2017-12-14 22:38:13 +0800 (Thu, 14 Dec 2017) | 1 line
------------------------------------------------------------------------
r33 | xxj | 2017-12-14 22:36:55 +0800 (Thu, 14 Dec 2017) | 1 line
[root@Python sadoc]# svn log v3/v8.log
------------------------------------------------------------------------
r35 | admin | 2017-12-14 22:57:00 +0800 (Thu, 14 Dec 2017) | 1 lin
------------------------------------------------------------------------
r19 | xxj | 2017-12-14 04:03:08 +0800 (Thu, 14 Dec 2017) | 1 line
------------------------------------------------------------------------
r12 | xxj | 2017-12-14 02:17:31 +0800 (Thu, 14 Dec 2017) | 1 line
haha
------------------------------------------------------------------------
r8 | xxj | 2017-12-14 02:05:38 +0800 (Thu, 14 Dec 2017) | 1 line
add v8
------------------------------------------------------------------------
5. SVN 常用命令
5.1 add
add PATH...
* svn add --force*
表示目录下所有文件,--force 表示强制,如果不加--force,当目录在版本控制下而该目录下的文件无版本控制,则添加不到。
添加到版本控制
[root@Python sadoc]# mkdir v9
[root@Python sadoc]# touch v9/v9.log
[root@Python sadoc]# svn add /root/sadoc
svn: '/root' is not a working copy
[root@Python sadoc]# svn add /root/sadoc/v9
A /root/sadoc/v9
A /root/sadoc/v9/v9.log
[root@Python sadoc]# svn st
A v3/v8.log
A v9
A v9/v9.log
5.2 commit
commit [PATH...] -m "注释信息"
将工作副本中的修改提交到svn服务器版本库(版本号+1)
[root@Python sadoc]# svn st
A v3/v8.log
A v9
A v9/v9.log
[root@Python sadoc]# svn up
At revision 7.
[root@Python sadoc]# svn ci -m "add v8"
Adding v3/v8.log
Adding v9
Adding v9/v9.log
Transmitting file data ..
Committed revision 8.
[root@Python sadoc]# svn st
[root@Python sadoc]#
5.3 update
update [PATH...]
更新工作副本(默认更新的最新版)
[root@Python sadoc]# svn update --help
update (up): Bring changes from the repository into the working copy.
usage: update [PATH...]
A Added
D Deleted
U Updated
C Conflict
G Merged
E Existed
[root@Python sadoc]# svn up
D v5.txt
A V2/新建文件夹
U v7.log
Updated to revision 9.
5.4 delete
1. delete PATH...
2. delete URL...
从版本库中删除文件或目录
[root@Python sadoc]# svn st
[root@Python sadoc]# ls
branch tags trunk V1 V2 v3 v7.log v9 新建文件夹
[root@Python sadoc]# svn del v7.log
D v7.log
[root@Python sadoc]# svn st
D v7.log
[root@Python sadoc]# svn up
At revision 15.
[root@Python sadoc]# svn st
D v7.log
[root@Python sadoc]# svn ci -m "D v7"
Deleting v7.log
Committed revision 16.
[root@Python sadoc]# svn st
5.5 diff
版本差异比较
[root@Python sadoc]# svn diff --help
diff (di): Display the differences between two revisions or paths.
usage: 1. diff [-c M | -r N[:M]] [TARGET[@REV]...]
2. diff [-r N[:M]] --old=OLD-TGT[@OLDREV] [--new=NEW-TGT[@NEWREV]] \
[PATH...]
3. diff OLD-URL[@OLDREV] NEW-URL[@NEWREV]
[root@Python sadoc]# vim v3/v8.log
[root@Python sadoc]# svn st
M v3/v8.log
[root@Python sadoc]# svn diff
# 当前版本和工作副本的差异
Index: v3/v8.log
===================================================================
--- v3/v8.log (revision 18)
+++ v3/v8.log (working copy)
@@ -1,3 +1,4 @@
12
14
-xj
+xxj
+111111111111111111111
[root@Python sadoc]# svn ci -m ""
Sending v3/v8.log
Transmitting file data .
Committed revision 19.
[root@Python sadoc]# svn diff
[root@Python sadoc]# svn diff -r 10
# 某个历史版本与工作副本的差异
Index: v3/v8.log
===================================================================
--- v3/v8.log (revision 10)
+++ v3/v8.log (working copy)
@@ -0,0 +1,4 @@
+12
+14
+xxj
+111111111111111111111
Index: v7.log
===================================================================
--- v7.log (revision 10)
+++ v7.log (working copy)
@@ -1,2 +0,0 @@
-7777
-10
[root@Python sadoc]# svn diff -r 10:11
# 两个历史版本间的差异
Index: v7.log
===================================================================
--- v7.log (revision 10)
+++ v7.log (revision 11)
@@ -1,2 +1,3 @@
7777
10
+11
5.6 mkdir
创建目录并增加到版本控制
[root@Python sadoc]# svn mkdir --help
mkdir: Create a new directory under version control.
usage: 1. mkdir PATH...
2. mkdir URL...
[root@Python sadoc]# svn mkdir xxj
A xxj
5.7 revert
* svn revert [-R] [filename|]**
工作副本还原,将工作副本还原成未提交前的状态
[root@Python ~]# svn revert --help
revert: Restore pristine working copy file (undo most local edits).
usage: revert PATH...
Note: this subcommand does not require network access, and resolves
any conflicted states. However, it does not restore removed directories.
Valid options:
--targets ARG : pass contents of file ARG as additional args
-R [--recursive] : descend recursively, same as --depth=infinity
[root@Python sadoc]# vim t1/t2/t3/test.md
[root@Python sadoc]# svn st
M t1/t2/t3/test.md
[root@Python sadoc]# svn revert -R t1
Reverted 't1/t2/t3/test.md'
三. 冲突
1. 冲突
在项目中,基本不可避免多个人同时参与一个项目,因此就可能会出现多个人同时修改一个文件的情况,就不可避免的会出现冲突。svn已经很聪明了,如果你和别人对于同一个文件的修改之间不存在重叠(比如你在文件最开始增加了一行,而你同事在文件的结尾出增加了一行(好像只对纯文本文档)),svn会自动将你们的修改进行合并,然而意外总是会发生,而且超出了svn的处理范围,只好采用人工智能(手工)来进行合并了。
1.1 文件冲突
当两名或更多开发人员修改了同一个文件中相邻或相同的行时就会发生文件冲突。由于 Subversion 不知道你的项目的具体情况,它把解决冲突的工作留给了开发人员。
1.2 树冲突
当一名开发人员移动、重命名、删除一个文件或文件夹,而另一名开发人员也对它们进行了移动、重命名、删除或者仅仅是修改时就会发生树冲突。非文件冲突就是树冲突
2. 冲突产生的条件
- 冲突常出现于工作副本长时间未更新时
- 更新到的数据与工作副本的修改正好在同一处
3. 如何尽可能的避免冲突
经常update
4. 如何解决冲突
文本冲突
[root@Python sadoc]# svn resolve --help
resolve: Resolve conflicts on working copy files or directories.
usage: resolve --accept=ARG [PATH...]
Note: the --accept option is currently required.
Valid options:
--targets ARG : pass contents of file ARG as additional args
-R [--recursive] : descend recursively, same as --depth=infinity
--depth ARG : limit operation by depth ARG ('empty', 'files',
'immediates', or 'infinity')
-q [--quiet] : print nothing, or only summary information
--accept ARG : specify automatic conflict resolution source
('base', 'working', 'mine-conflict',
'theirs-conflict', 'mine-full', 'theirs-full')
[root@Python sadoc]# svn resolved --help
resolved: Remove 'conflicted' state on working copy files or directories.
usage: resolved PATH...
C:\workspace\test>svn up
Conflict discovered in 'test.txt'.
Select: (p) postpone, (df) diff-full, (e) edit,
(mc) mine-conflict, (tc) theirs-conflict,
(s) show all options:
svn detects that theres a conflict here and require you to take some kind of action.
If you type 's' here you will get a list of the commands and meaning
如果你输入s选项,则会列出所有svn解决冲突的选项,如下所示:
(e) edit - change merged file in an editor #直接进入编辑
(df) diff-full - show all changes made to merged file #显示更改至目标文件的所有变化
(r) resolved - accept merged version of file
(dc) display-conflict - show all conflicts (ignoring merged version) #显示所有冲突
(mc) mine-conflict - accept my version for all conflicts (same) #冲突以本地为准
(tc) theirs-conflict - accept their version for all conflicts (same) #冲突以服务器为准
(mf) mine-full - accept my version of entire file (even non-conflicts)#完全以本地为准
(tf) theirs-full - accept their version of entire file (same) #完全以服务器为准
(p) postpone - mark the conflict to be resolved later #标记冲突,稍后解决
(l) launch - launch external tool to resolve conflict
(s) show all - show this list
【选择处理方式一:df】
If you type 'df' it will show you a all the conflicts in the following format
选择选项df,则会按如下格式显示所有冲突
Select: (p) postpone, (df) diff-full, (e) edit,
(mc) mine-conflict, (tc) theirs-conflict,
(s) show all options: df
--- .svn/text-base/test.txt.svn-base Tue Aug 10 10:59:38 2010
+++ .svn/tmp/test.txt.2.tmp Tue Aug 10 11:33:24 2010
@@ -1 +1,3 @@
-test
\ No newline at end of file
+<<<<<<< .mine +test User2 making conflict======= +User1 is making a conflict test>>>>>>> .r3
'e' option will open the conflicted file in the text editor that you configured for svn to use. In this case it will show
<<<<<<< .mine test User2 making conflict======= User1 is making a conflict test>>>>>>> .r3
You can resolve the conflict here by changing the text to what you desire.
For example:
你可以解决冲突通过改变文件内容,例如vim test.txt
User1 is making a conflict test User2 making conflict
save your changes and exit your text editor and it will give you the conflict options again. Now if you use the 'r' it will mark the file is merged with a 'G'. A status of 'G' means there was a conflict and it has been resolved.
保存更改,又出现刚才的选项。此时你使用r选项,则会合并文件。如下所示:
Select: (p) postpone, (df) diff-full, (e) edit, (r) resolved,
(mc) mine-conflict, (tc) theirs-conflict,
(s) show all options: e
Select: (p) postpone, (df) diff-full, (e) edit, (r) resolved,
(mc) mine-conflict, (tc) theirs-conflict,
(s) show all options: r
G test.txt
Updated to revision 3.
you can now check the status with svn status. You see that test.txt is marked as 'M' all thats left to do is commit.
检查svn状态,你会发现文件test.txt前面已变成M
C:\workspace\test2>svn st
M test.txt
C:\workspace\test2>svn ci -m "conflict resolved"
Sending test.txt
Transmitting file data .
Committed revision 4.
【选择处理方式二:p】
Sometimes the conflicts are a bit more extensive and it requires more time or better tools to resolve the conflict in these cases you can chose 'p' to postpone the resolution.
有时,冲突会复杂一些,可能需要借助其他工具才能解决,这时你可以使用选项p
Select: (p) postpone, (df) diff-full, (e) edit, (r) resolved,
(mc) mine-conflict, (tc) theirs-conflict,
(s) show all options: p
C test.txt
Updated to revision 3.
Summary of conflicts:
Text conflicts: 1
Now if you look in your directory you will see that svn has created a few extra files for you.
此时,查看当前文件夹下,出现了如下几个文件
08/10/2010 11:44 AM 94 test.txt
08/10/2010 11:44 AM 26 test.txt.mine
08/10/2010 11:44 AM 27 test.txt.r2
08/10/2010 11:44 AM 31 test.txt.r3
The test.txt file is now a file with both User2 and User1′s changes but marked.
文件test.txt包含了用户1和用户2的更改。
<<<<<<< .mine test User2 making conflict======= User1 am making a conflict test>>>>>>> .r3
test.txt.mine is User2′s copy.
文件.txt.mine保存了用户2的内容
test User2 making conflict
test.txt.r2 is the original base copy
文件.txt.r2是未冲突前的内容
test
test.txt.r3 is the copy User1 commited
文件.txt.r3保存了用户1的内容
User1 is making a conflict test
At this point you can choose your favorite merge tools to merge the differences in a file.
这种情况下,你可以选择自己喜欢的对比工具,查看差别。
I suggest merging the differences into test.txt and the do a
我建议和并不同至文件test.txt中,如果如下命令:
C:\workspace\test>svn resolve --accept working test.txt
Resolved conflicted state of 'test.txt'
You can also use any of the other files if you wanted to and just pass resolve –accept a different argument. Here are the valid arguments
当然,你也可以使用其他文件,使用resolve -accept 加其他参数,共6个
(1)#svn resolve –accept base
Choose 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.
使用1.txt.r2作为最后提交的版本
(2)#svn resolve –accept working
Assuming that you've manually handled the conflict resolution, choose the version of the file as it currently stands in your working copy.
使用当前拷贝即test.txt作为最后提交的版本
(3)#svn resolve –accept mine-full
Resolve all conflicted files with copies of the files as they stood immediately before you ran svn update.
使用test.txt.mine作为最后提交的版本
(4)#svn resolve –accept theirs-full
Resolve all conflicted files with copies of the files that were fetched from the server when you ran svn update.
使用test.txt.r3作为最后提交的版本
(5)#svn resolve –accept mine-conflict
冲突的部分以本地修改为准
(6)#svn resolve –accept theirs-conflict
冲突的部分以服务器端修改为准
执行一下:svn resolved test.txt。
Now you are ready to commit.
然后提交
C:\workspace\test>svn ci -m "conflict resolved"
Sending test.txt
Transmitting file data .
Committed revision 4.
四. 锁定与解锁
svn lock
锁定文件,防止其它成员对文件进行提交
svn unlock
解锁文件
svn ci 提交后会自动解锁,如果不想自动解锁则使用--no-unlock : don'
[root@Python sadoc]# svn lock --help
lock: Lock working copy paths or URLs in the repository, so that
no other user can commit changes to them.
usage: lock TARGET...
Use --force to steal the lock from another user or working copy.
[root@Python sadoc]# svn unlock --help
unlock: Unlock working copy paths or URLs.
usage: unlock TARGET...
Use --force to break the lock.
[root@Python sadoc]# svn lock v3/v8.log
'v8.log' locked by user 'xxj'.
[root@Python sadoc]# svn st
K v3/v8.log
[root@Python sadoc]# svn unlock v3/v8.log
'v8.log' unlocked.
[root@Python sadoc]# svn st
五. copy
copy SRC[@REV]... DST
svn copy --help
copy (cp): Duplicate something in working copy or repository, remembering
history.
usage: copy SRC[@REV]... DST
When copying multiple sources, they will be added as children of DST,
which must be a directory.
SRC and DST can each be either a working copy (WC) path or URL:
WC -> WC: copy and schedule for addition (with history)
WC -> URL: immediately commit a copy of WC to URL
URL -> WC: check out URL into WC, schedule for addition
URL -> URL: complete server-side copy; used to branch and tag
All the SRCs must be of the same type.
copy 分四大类:
1. 工作副本 -->工作副本
[root@Python sadoc]# svn copy v3/v8.log copy.log
A copy.log
[root@Python sadoc]# svn st
A + copy.log
[root@Python sadoc]# cp v3/v8.log xxj.log
[root@Python sadoc]# svn st
? xxj.log
A + copy.log
[root@Python sadoc]# svn add xxj.log
A xxj.log
[root@Python sadoc]# svn st
A xxj.log
A + copy.log
[root@Python sadoc]# svn cp -r 30 v3/v8.log copy2.log
A copy2.log
[root@Python sadoc]# svn st
A xxj.log
A + copy.log
A + copy2.log
2. 工作副本 -->版本库
不支持跨库
[root@Python sadoc]# svn cp v3/v8.log svn://192.168.10.1/sadoc
svn: No repository found in 'svn://192.168.10.1'
[root@Python sadoc]# svn cp v3/v8.log svn://192.168.10.1/sadoc/target.html
svn: Could not use external editor to fetch log message; consider setting the $SVN_EDITOR environment variable or using the --message (-m) or --file (-F) options
svn: None of the environment variables SVN_EDITOR, VISUAL or EDITOR are set, and no 'editor-cmd' run-time configuration option was found
[root@Python sadoc]# svn cp v3/v8.log svn://192.168.10.1/sadoc/target.html -m ""
Committed revision 38.
从工作副本copy到版本库就直接提交了(跳过了本地工作副本)
3. 版本库 -->工作副本
支持跨库copy
记住不允许跨库提交
4. 版本库-->版本库
就是创建分支
svn cp svn://192.168.10.1/sadoc/ svn://192.168.10.1/sadoc/trunk -m "mkdir trunk"
Committed revision 52.
# 创建主干版本
# svn://192.168.10.1/sadoc/ 这里带/是复制该目录下的所有文件,不带就是复制该目录
[root@Node1 sadoc]# svn cp svn://192.168.10.1/sadoc/trunk svn://192.168.10.1/sadoc/branch -m "mkdir branch"
Committed revision 53.
# 创建分支版本
六. hooks
1. hooks简介
hooks 钩子
何为钩子?
可以理解为触发器,当执行某些特定操作时触发执行预先设定好的任务。
SVN的hooks模版功能介绍
start-commit 提交前触发事务
pre-commit 提交完成前触发事务,在Subversion transaction完毕之后,在提交之前,执行该脚本
post-commit 提交完成时触发事务;在提交完成,成功创建版本之后执行该钩子,提交已经完成,不可更改,因此本脚本的返回值被忽略
post-lock 对文件进行加锁操作之后执行该脚本
post-revprop-change 在修改revision 属性之后,执行该脚本,因为修改稿已经完成,不可更改,因此本脚本的返回值被忽略(不过实际上的实现似乎是该脚本的正确执行与否英雄属性修改)
[root@Node1 sadoc]# ls
conf db format hooks locks README.txt
[root@Node1 sadoc]# ls hooks/
post-commit.tmpl post-unlock.tmpl pre-revprop-change.tmpl
post-lock.tmpl pre-commit.tmpl pre-unlock.tmpl
post-revprop-change.tmpl pre-lock.tmpl start-commit.tmpl
# hooks目录下有很多钩子模版文件(其实就是shell脚本), 只需要复制模版去掉.tmpl后缀就可以生效使用了
svn 钩子在生产中的应用举例:
- 限制上传文件扩展名及大小
- svn更新自动周知,MSN,邮件或短信周知
- SVN更新触发实时rsync推送
例:
/usr/bin/svn up --username admin --password admin /data/www && /usr/bin/rsync -az --delete /data/www /tmp/
写钩子脚本的一些注意事项:
- 钩子脚本的权限运行svn执行
- 写钩子脚本时要使用绝对路径,因为svn考虑安全问题,不会调用系统环境变量,所有发现手动执行post-commit是没有问题,但svn自动执行也可能会无法执行。
- 尽可能定义环境变量,尽可能加上用户和密码,如果只是手动一样会更新,但自动触发可能会失败。
七. 版本库相关操作
1. 版本库精简
一个版本库使用时间长了,版本号越来越大,版本库占用的空间越来越多,到了一定时间我们可能需要对版本库进行精简,把早些时候的版本丢弃,来达到瘦身的目的。
1.1 停止svnserve服务
进行版本库精简需要先停止svn服务,防止此时有人提交发生错误
[root@Node1 hooks]# pkill svnserve
1.2 备份需要的版本数据
需要把想要保留下的版本数据备份出来
[root@Node1 hooks]# svnadmin dump --help
dump: usage: svnadmin dump REPOS_PATH [-r LOWER[:UPPER] [--incremental]]
Dump the contents of filesystem to stdout in a 'dumpfile'
portable format, sending feedback to stderr. Dump revisions
LOWER rev through UPPER rev. If no revisions are given, dump all
revision trees. If only LOWER is given, dump that one revision tree.
If --incremental is passed, the first revision dumped will describe
only the paths changed in that revision; otherwise it will describe
every path present in the repository as of that revision. (In either
case, the second and subsequent revisions, if any, describe only paths
changed in those revisions.)
# 注意这里使用的版本库文件系统路径(就是数据库的路径)
Valid options:
-r [--revision] ARG : specify revision number ARG (or X:Y range)
--incremental : dump incrementally
--deltas : use deltas in dump output
-q [--quiet] : no progress (only errors) to stderr
# 备份版本号30--56的数据
[root@Node1 hooks]# svnadmin dump /application/svndata/sadoc/ -r 30:56 > /tmp/sadoc.repo
#
* Dumped revision 30.
* Dumped revision 31.
* Dumped revision 32.
* Dumped revision 33.
* Dumped revision 34.
* Dumped revision 35.
* Dumped revision 36.
* Dumped revision 37.
* Dumped revision 38.
* Dumped revision 39.
* Dumped revision 40.
* Dumped revision 41.
* Dumped revision 42.
* Dumped revision 43.
* Dumped revision 44.
* Dumped revision 45.
* Dumped revision 46.
* Dumped revision 47.
* Dumped revision 48.
* Dumped revision 49.
* Dumped revision 50.
* Dumped revision 51.
* Dumped revision 52.
* Dumped revision 53.
* Dumped revision 54.
* Dumped revision 55.
* Dumped revision 56.
1.3 创建新的版本库并导入备份数据
[root@Node1 svndata]# svdadmin create newsadoc
-bash: svdadmin: command not found
[root@Node1 svndata]#
[root@Node1 svndata]# svnadmin create newsadoc
[root@Node1 svndata]# ls
newsadoc sadoc t1 t2
[root@Node1 svndata]# svnadmin load newsadoc/ < /tmp/sadoc.repo
<<< Started new transaction, based on original revision 30
* adding path : 新建文件夹 ... done.
* adding path : 新建文本文档.txt ... done.
* adding path : trunk ... done.
* adding path : t1 ... done.
* adding path : t1/t2 ... done.
* adding path : t1/t2/t3 ... done.
* adding path : t1/t2/t3/test.md ... done.
* adding path : 新建文本文档 (2).txt ... done.
* adding path : V1 ... done.
* adding path : V1/1.txt ... done.
* adding path : V2 ... done.
* adding path : V2/新建文件夹 ... done.
* adding path : v3 ... done.
* adding path : v3/v8.log ... done.
* adding path : branch ... done.
* adding path : branch/v4 ... done.
* adding path : v8 ... done.
* adding path : tags ... done.
* adding path : v9 ... done.
* adding path : v9/v9.log ... done.
------- Committed new rev 1 (loaded from original rev 30) >>>
<<< Started new transaction, based on original revision 31
* deleting path : V1/1.txt ... done.
------- Committed new rev 2 (loaded from original rev 31) >>>
<<< Started new transaction, based on original revision 55
* adding path : xx ... done.
------- Committed new rev 26 (loaded from original rev 55) >>>
<<< Started new transaction, based on original revision 56
* editing path : copy.log ... done.
------- Committed new rev 27 (loaded from original rev 56) >>>
1.4 复制配置文件并启动svnserve
[root@Node1 svndata]# cp -a sadoc/conf newsadoc/
[root@Python ~]# svn co svn://192.168.10.1/newsadoc
A newsadoc/新建文件夹
A newsadoc/xj
A newsadoc/t1
A newsadoc/trunk/v9/v9.log
Checked out revision 27.
[root@Python ~]# svn info newsadoc
Path: newsadoc
URL: svn://192.168.10.1/newsadoc
Repository Root: svn://192.168.10.1/newsadoc
Repository UUID: 1aa20afc-4318-4497-a077-c0f8c47884c4
Revision: 27
Node Kind: directory
Schedule: normal
Last Changed Author: xxj
Last Changed Rev: 27
Last Changed Date: 2017-12-15 20:34:36 +0800 (Fri, 15 Dec 2017)
[root@Python ~]# svn log newsadoc
------------------------------------------------------------------------
r27 | xxj | 2017-12-15 20:34:36 +0800 (Fri, 15 Dec 2017) | 1 line
------------------------------------------------------------------------
r1 | xxj | 2017-12-14 22:29:46 +0800 (Thu, 14 Dec 2017) | 1 line
------------------------------------------------------------------------
2. 版本库迁移与switch重定向
- 停止svnserve服务
- 把版本库文件系统目录(数据库)拷贝到新服务器上
- 在新服务器上运行svnserve
[root@Python newsadoc]# svn switch --help
switch (sw): Update the working copy to a different URL.
usage: 1. switch URL[@PEGREV] [PATH]
2. switch --relocate FROM TO [PATH...]
[root@Python newsadoc]# svn up
svn: No repository found in 'svn://192.168.10.1/newsadoc'
[root@Python newsadoc]# svn sw svn://192.168.10.1/sanew .
svn: 'svn://192.168.10.1/newsadoc'
is not the same repository as
'svn://192.168.10.1/sanew'
[root@Python newsadoc]# svn sw --relocate svn://192.168.10.1/newsadoc svn://192.168.10.1/sanew