简介

版本管理基本上是多人协作开发中必不可少的工具,常用的版本管理工具有:svn和git。虽然都有可视化的工具帮助我们使用这些工具,然而当你用上命令行之后,我想你会选择抛弃这些可视化工具。下面是我整理的一些常用的svn命令。

SVN命令格式

svn命令格式: svn <subcommand> [options] [args]
subcommand 是子命令
options 是选项,可选
args 是参数,可选

SVN常用命令

说明: 绝大部分svn命令都是在svn的工作目录下执行的, 只有少数几个例外.

1. 帮助和日志查看

1
2
3
4
5
6
7
svn help/h --查看帮助信息
svn help <subcommand> --查看子命令的帮助信息
svn --version -- 查看程序版本信息和RA模块
svn --version --quiet --仅查看snv的版本号
svn log --查看所有日志
svn log -l 10 --查看最新10条日志
svn info --show-item revision --查看工程的版本号

2. 检出/查看/导入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 检出代码
svn checkout/co [directory] project(本地目录名,可选)
# 检出版本3
svn checkout/co –revision/r 3 [directory] project(本地目录名,可选)
# 查看检出版本信息(注意:要进入到svn的工作目录中去)
svn info
# 导入(import)项目,项目尚未创建,将本地的目录放到SVN版本仓库中
svn import project(本地目录名) [directory]
# 查看svn工作目录下的文件和目录
svn list/ls
# 查看svn最新修改的最新版本号
svn info yourdir --show-item last-changed-revision

3. 更新/增加/修改/删除/重命名/拷贝/创建目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 更新仓库内容到本地
svn update/up
# 更新到版本3
svn update/up –revision/r 3
# 增加一些新的文件,纳入项目的版本控制
svn add a.py b.py ...
# 删除废弃的不用的文件
svn delete/del/remove/rm a.py
# 重命名文件
svn move/mv a.py aa.py
# 新增目录
svn mkdir mydir
# 拷贝
svn copy/cp srcdir/a.py dstdir/a.py

4. 检查/查看差异

1
2
3
4
5
6
7
8
9
10
11
# 检查修改状态
svn status/stat/st
# 对比一个目录下的差异
svn diff/di folder(本地目录名,可选,默认当前目录)
# 对比具体文本差异
svn diff/di –revision/r 3 index.html
# 查看index.html版本3和版本4的差别
svn diff/di –revision/r 3:4 index.html

5. 取消修改

1
2
3
4
5
# 回滚整个目录的修改
svn revert . -R/--recursive
# 撤销某个文件的修改
svn revert a.py

6. 分支操作

1
2
3
4
5
6
7
8
# 创建分支
svn copy/cp svn://xxx.com/repo/trunk svn://xxx.com/repo/branches/test -m 'make branch test'
# 将工作目录转到分支
svn switch/sw svn://xxx.com/repo/branches/test
# 将工作目录转到主干
svn switch/sw svn://xxx.com/repo/trunk

7. 合并一个分支到主干

1
2
3
4
5
6
7
8
9
10
11
# 查询出自创建分支以后分支上的所有修改,最下面的那个版本号就是我们要找的版本号
cd branches/test(分支目录)
svn log –stop-on-copy
# 查询出自创建分支以后分支上的所有修改,最下面的那个版本号就是我们要找的版本号
cd trunk(主干目录)
svn -q –stop-on-copy svn://xxx.com/repo/branches/test(分支url)
# 合并到主干
cd trunk(主干目录)
svn merge -r 11340(分支版本):HEAD svn://xxx.com/repo/branches/test(分支url)

8. 两个分支合并

1
2
3
4
5
6
7
8
9
10
# 假设99是从旧主干引出,100打完tag,表示是新主干。合并最新代码的意思是:将新主干与旧主干比对,并添加到99中。这样99既有自己的新增的代码,也同时有最新线上的代码。
cd 99_Branch
svn merge svn://xxx.com/repo/tags/project_Old_BL svn://xxx.com/repo/tags/project_New_BL svn ci -m 'merge 100 trunk'
# 但是后来,其他人又向100提了代码,所以还需要将100分支(即打了tag后的100,打了tag前的100已是主干)合并至99中。合并办法:找出100分支,比对与新主干之间的差别,并添加到99中。这样99就有最新的全部代码了。
cd 99_Branch
svn merge svn://xxx.com/repo/tags/project_New_BL svn:/xxx.com/repo/branches/100_Branch svn ci -m 'merge 100 branch'
# 合并主干到分支
svn merge -r LastRevisionMergedFromTrunkToBranch:HEAD svn:/xxx.com/repo/branches/99_Branch

9. 发布

1
2
# 给当前主干打个标签,并且这个标签不再改动了,但是实际上标签和分支是一个意思,你可以在标签上继续做改动,但这不推荐。
svn copy/cp svn://xxx.com/repo/trunk svn://xxx.com/repo/tags/RB-1.0

10. 提交/导出代码

1
2
3
4
5
# 提交代码
svn commit/ci -m 'message'
# 导出代码, 不包含svn版本信息
svn export svn://xxx.com/repo/branches/test folder(本地目录)

11. 解决冲突

当发生冲突的时候,会提示如下信息:

Conflict discovered in ‘index.html’.
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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
如果你输入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
一般我们会选择p稍后解决冲突,这样会生成三个文件:.mine, .rOLDREV, .rNEWREV。
比如:index.html index.html.mine index.html.r1 index.html.r2
解决冲突方法大致有一下几种:
1).手工修改index.html文件,然后将当前index.html作为最后提交的版本
svn resolve index.html –-accept working
2).选择base版本,即index.html.rOLDREV作为最后提交的版本
svn resolve index.html –-accept base
3).使用index.html.rNEWREV作为最后提交的版本
svn resolve index.html –-accept theirs-full
4).使用index.html.mine作为最后提交的版本
svn resolve index.html –-accept mine-full
# 或者用下面这条命令也可以
svn resolve index.html –-accept theirs-conflict

12. 查看最近svn几次的版本号

通过查看svn日志,然后用正则表达式匹配出版本号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 获取最近几次提交的版本号
def get_commit_revisions(svn_path, commit_times="5"):
output = subprocess.check_output(
["svn", "log", svn_path, "-v", "--limit", commit_times]).decode("gbk").strip()
svn_logs = [item.strip() for item in output.splitlines() if item]
# 存放最近几次提交的版本号
revisions_info = []
# 匹配版本号
pattern1 = re.compile(r'^r[0-9]* ')
for msg in svn_logs:
match1 = pattern1.match(msg)
if match1:
revision = match1.group().strip()
revisions_info.append(revision[1:])
return revisions_info
# 获取最新修改的版本号
def get_base_revision(svn_path):
revision = subprocess.check_output(
["svn", "info", svn_path, "--show-item", "last-changed-revision"]).decode("gbk").strip()
print("revision = {}".format(revision))
return revision

参考