SVN的基本使用

前言

上一篇简单介绍了SVN,如需阅读,可以点这里查看: SVN的介绍与使用流程
这篇主要介绍如何将代码纳入SVN控制,然后对代码进行一些常用的指令的介绍,包括更新、编辑、编辑冲突等。
这里多是使用命令行的方式使用SVN,没有使用小乌龟图形界面,因为图形界面操作很简单。其实使用图形很方便,也很快捷。但在Linux系统、或者Linux服务器编译,那么就必须使用命令行的方式了。所以,掌握SVN命令行,也是必要的。

本章首先介绍如何把文件纳入 Subversion, 然后对代码 进行首次检出, 接下来将对代码进行一些修改, 并检查修改前后的具体差异. 还将会看到如何把其他人的修改应用到自己的工作副本中, 检查修改并解决可能的冲突。

基本工作周期

我们知道,Subversion 支持的特性与选项非常丰富,非常强大。但是对于程序员, 能够在日常工作中用到的却很少。 本节将介绍日常工作中最常用到的 Subversion 操作。

典型的工作周期是这样的:
1.检出更新工作副本 :每次提交前需要保证项目是最新的,用到的命令:
svn update

2.编辑工作副本:最常见的修改就是编辑已有文件的内容, 但有时还要添加, 删除, 复制和移动文件或目录,负责 处理工作副本的结构性调整。用到的命令:
svn add
svn delete
svn copy
svn move

3.审核修改: 查看工作副本发生了哪些变化。用到的命令:
svn status
svn diff

4. 修正错误: 在审核修改时可能会发现某些修改是不正确的。有时候修正错误最简单的方式是撤消所有的修改, 把文件或目 录恢复到修改前的样子重新开始。用到的命令:
svn revert

5. 解决冲突: 即合并其他人的修改, 当正在修改文件时, 其他人可能已经把自己的修改提交到了服务器上. 为了防止 在提交修改时, 由于工作副本过旧导致提交失败, 用户需要把其他人的修改 更新到本地。如果命令 的执行结果有冲突产生, 用户需要用命令 svn resolve 解决冲突。用到的命令:
svn update
svn resolved

6.提交你的修改: 将工作副本的修改提交到仓库中, 如果修改 被接受, 其他用户就可以看到这些修改。用到的命令:
svn commit

大致的流程图,如下所示:


基本用法

相信经常使用命令行的人,那么多命令不需要每条背起来,都有相应的帮助文档,Subversion也是一样。所以,首先介绍下如何查看帮助文档。
命令 svn help 是 打开内置文档的入口,如:
svn help:
用法: svn <subcommand> [options] [args]
Subversion 命令行客户端,版本 1.8.15。
使用“svn help <subcommand>” 显示子命令的帮助信息。
使用“svn --version”查看程序的版本号和版本库访问模块,或者
使用“svn --version --quiet”只查看程序的版本号。

大多数的子命令可接受文件或目录参数,对目录进行递归处理。
如果没有指定参数,默认对当前目录(包含当前目录)递归处理。

可用的子命令: 
   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)
   patch
   propdel (pdel, pd)
   propedit (pedit, pe)
   propget (pget, pg)
   proplist (plist, pl)
   propset (pset, ps)
   relocate
   resolve
   resolved
   revert
   status (stat, st)
   switch (sw)
   unlock
   update (up)
   upgrade
Subversion 是版本控制工具。
欲取得详细资料,请参阅 http://subversion.apache.org/
帮助文档的用法: svn <subcommand> [options] [args]
<subcommand>:子命令,如上面所示
[options]:选项,作用是命令修饰符 ,可选。
注:其有两种形式: 短选项由一个连字符和一个英文字母组成,如 svn commit -m ARG ;长选项以两个连续的连字符开始, 后跟几个英文字母和连字符,如svn commit --message ARG。 每个选项至少有长选项,一般只有常用的才有短选项。
[args] :参数,比如目标路径,可选

检测/更新工作副本

用户开始使用仓库是通过执行 检出 (checkout) 命令,检出仓库中的目录将会在用户的本地主机上创建一个该目录的工作副本。除非特意指定, 否则这个副本将包含仓库最新版本的数据。
svn checkout <url>
检测工作副本,在本地创建的目录名是检出命令中 URL 参数的最后一个分量,不过,也可以也允许用户自己指定一个目录名,只要在URL后面添加一个路径即可,如:
 svn checkout http://svn.example.com/svn/repo/trunk   myWorking
svn update (up)
每次工作之前,需要更新自己本地的工作副本, 以获取其他人提交的修改,也避免导致冲突,这是一个好习惯,可以使用 svn update 。如果最新的版本有问题,想回退到某个版本,则可以:svn update -r <versionNum>

修改工作副本

工作副本支持的修改类型分为两种:文件修改 (file changes) 和 目录修改 (tree changes)。
目录修改涉及到目录结构 的变化,例如添加和删除文件,重命名文件和目录,复制文件和目录。文件修改和目录修改只有在提交后才会更新到仓库中。
下面是最常用到的 5 个改变目录结构的 Subversion 子命令:
svn add FOO
这个命令把文件, 目录或软链接 FOO 添加到需要进行版本控制的名单中,在下一次提交时, FOO 就会正式添加到仓库里。如果 FOO 是一个目录,那么目录内的所有内容都会被添加到仓库中。如果只想添加 FOO它自己,就带上选项 --depth=empty。

svn delete FOO
从工作副本中删除文件, 目录或符号链接 FOO。

svn copy FOO BAR
从 FOO 复制出一个 BAR, 并把 BAR 添加到 需要进行版本控制的名单中. BAR 被提交到仓库 后, Subversion 会记录它是由 FOO 复制得到的。除非带上选项 --parents, 否则 svn copy 不会创建父目录。

svn move FOO BAR
这条命令等价于 svn copy FOO BAR; svn delete FOO , 也就是从 FOO 复制出一个 BAR,然后再删除 FOO。

svn mkdir FOO
该命令等价于 mkdir FOO;svn add FOO;也就是创建一个新目录 FOO, 并把它添加到仓库中。

审核修改工作副本

在提交之前,应该查看 一下自己到底修改了哪些东西,通过检查修改, 用户可以写出更准确的提交日志 ,同时可以撤销不必要的修改。使用命令 svn status 查看修改的整体概述, 用命令 svn diff 查看修改的细节。
svn status
如果在工作副本的根目录不加任何参数地执行 svn status,Subversion 就会检查并报告所有文件目录的修改,并显示目录的状态, 其中最常的几种字符或状态是:
? :文件不在版本控制的名单中.
A :文件是新增的,在下一次提交时就会加入到仓库中。
C :文件 item 有未解决的冲突, 意思是说从 服务器收到的更新和该文件的本地修改有所重叠,此时必须解决掉冲突后才能向仓库提交修改。
D :文件已被删除, 在下一次提交时就会从仓库中删除。
M :文件 item 的内容被修改。

其还可以添加一些参数,常用的是:
svn status <path>:指定一个目录,只会输出和该路径相关的状态信息。
svn status  --verbose (-v): 输出当前目录中每一项的状态, 即使是未被修改的项目
svn status --show-updates (-u) --verbose (-v):显示上一次更新之后, 哪些文件在仓库中又被更新了,查看本地过时文件(需要网络),如:
$ svn status -u -v
M      *        44        23    sally     README
M               44        20    harry     bar.c   
         *        44        35    harry     stuff/trout.c
D                44        19    ira       stuff/fish.c
A                0         ?     ?        stuff/things/bloo.hStatus against revision:   46
注意带有星号的那 2 行, 如果此时执行 svn update, 就会从仓库收到 README 和 trout.c 的更新。

svn diff 
在工作副本的根目录不加任何参数地执行 svn diff,文件的变化以标准差异 (unified diff) 的格式输出,这种格式把文件内容的变化描述成“块” (hunk) 或 “片断” (snippet),其中每一行文本都加上一个单字符前缀:
  • 空格表示该行没有变化;
  • 负号 (-) 表示该行被删除;
  • 正号 (+) 表示该行是新增的。
在 svn diff 的语境中, 这些冠以正负号的行显示了修改前的行和修改后的行分别是什么样子的。
这是一个执行 svn diff 的例子:
$ svn diff
Index: bar.c
===================================================================
--- bar.c	(revision 3)
+++ bar.c	(working copy)
@@ -1,7 +1,12 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <stdio.h>

 int main(void) {
-  printf("Sixty-four slices of American Cheese...\n");
+  printf("Sixty-five slices of American Cheese...\n");
 return 0;
 }

svn diff 在比较了工作副本中的文件和基文本后,再输出它们之间的差异。在命令的输出中, 新增的文件其每一行都被冠以正号;被删除的文件其每一行都被冠以负号。

常用的还有其他参数:
选项 --revision (-r) 传递了一对用冒号隔开的版本号, 命令就会比较这两个版本号的差异。
如:svn diff -r 2:3 rules.txt
如果只是一个版本号,没有冒号,那么就是比较当前工作副本和指定的仓库,
如:svn diff -r 3 rules.txt

修正错误

假设用户在查看 svn diff 的输出时发现针对某 一文件的修改都是错误的,也许这个文件就不应该被修改,也许重新开始 。Subversion 提供了一种简便的方法来撤消工作副本中的修改,利用缓存在基文本中的内容,把文件回滚到修改前的原始状态。用到的命令是 svn revert,可以撤消任何 一个未提交的修改。

解决冲突(难点重点)

冲突可以在仓库中的修改合并到本地工作副本的任何时候发生,执行svn update 就有可能产生冲突。那么当发生冲突 时 Subversion 如何通知的?以及应该如何处理它们?
假设在执行 svn update 后看到了如下 输出:
$ svn update
Updating '.':
Conflict discovered in 'bar.c'.
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:
报告说在把仓库的修改合并到文件 bar.c 时, 发现其中一些修改和本地未提交的修改产生了冲突。原因可能是其他人和用户都修改了同一行, 无论是因为什么, Subversion 在发现冲突时会马上把文件置成冲突状态, 然后询问用户他想怎么办。 用户可以从 Subversion 给出的几个选项中选择一个, 如果想看完整的选项列表, 就输入 s,下面简单介绍每一个选项。
(e) edit [edit]:使用环境变量 EDITOR 定义的编辑器打开 发生冲突的文件。
(df) diff-full:按照标准差异格式显示基础修订版和冲突的文件之间的差异。
(r) resolved:编辑完成后, 告诉 svn 用户已经解决了冲突, 现在应该接受文件的当前内容。
(dc) display-conflict:显示冲突的区域, 忽略合并成功的修改。
(mc) mine-conflict [mine-conflict]:丢弃从服务器收到的, 与本地冲突的所有修改, 但是接受不会产生 冲突的修改。
(tc) theirs-conflict [theirs-conflict]:丢弃与服务器产生冲突的所有本地修改, 但是保留不会产生冲突 的本地修改。
(mf) mine-full [mine-full]:丢弃从服务器收到的该文件的所有修改, 但是保留该文件的 本地修改。
(tf) theirs-full [theirs-full]:丢弃该文件的所有本地修改, 只使用从服务器收到的修改。
(m) merge:打开一个内部文件合并工具来解决冲突, 该选项从 Subversion 1.8 开始支持。
(l) launch:打开一个外部程序来解决冲突, 在第一次使用该选项之前需要完成 一些准备工作。
(p) postpone [postpone]:让文件停留在冲突状态, 在更新完成后再解决冲突。
(s) show all:显示所有的, 可以用在交互式的冲突解决中的命令。

如果是在图形界面TortoiseSVN解决冲突,相信还是挺容易的。但是在命令行处理,很多人多会有点害怕。接下来,选其中几个详细介绍下。

交互式地查看冲突差异 df dc
在决定如何交互地解决冲突之前, 有必要看一下冲突的内容, 其中有两个命令可以帮到我们。 第一个是 df:
…
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: df
--- .svn/text-base/sandwich.txt.svn-base      Tue Dec 11 21:33:57 2007
+++ .svn/tmp/tempfile.32.tmp     Tue Dec 11 21:34:33 2007
@@ -1 +1,5 @@
-Just buy a sandwich.
+<<<<<<< .mine
+Go pick up a cheesesteak.
+=======
+Bring me a taco!
+>>>>>>> .r32
差异内容的第一行显示了工作副本之前的内容 (版本号 BASE), 下一行是用户的修改,最后一行是从服务器收到的修改 (通常 是版本号 HEAD)。
第二个命令dc 和第一个比较类似,但是 dc 只会显示冲突区域,而不是文件的所有修改。另外,该命令显示冲突区域的格式也稍有不同,这种格式允许用户更方便地比较文件在三种状态下的内容:原始状态; 带有用户的本地修改,忽略服务器的冲突修改; 带有服务器的修改, 忽略用户的本地修改。
审核完这些命令提供的信息之后, 就可以采取下一下动作。

交互式地解决冲突差异
交互式地解决冲突的主要方法是使用一个内部文件合并工具, 该工具询问用户如何处理每一个冲突修改, 而且允许用户有选择地合并和编辑修改。
解决这些冲突,第 一个命令是  m (merge),从 Subversion 1.8 开 始支持, 该命令允许用户从众多选项中选择一个来解决冲突:
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: m
Merging 'Makefile'.
Conflicting section found during merge:
(1) their version (at line 24)                  |(2) your version (at line 24)
------------------------------------------------+------------------------------------------------
top_builddir = /bar                             |top_builddir = /foo
------------------------------------------------+------------------------------------------------
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:
从上面可以看到, 使用内部文件合并工具时, 用户可以循环遍历文件中 的每一个冲突区域, 对每一个冲突区域用户都可以选择一个不同的选项, 或者 推迟解决该冲突。
用命令  e (edit) 来手动地编辑带有冲突标记的文件。如果用户想用一个外部编辑器来选择本地修改的某些组合就可以使用该命令。 该命令会打开一个文本编辑器,文件编辑完毕后, 就要用命令 r (resolved) 告诉 Subversion 文件的冲突已经解决了。
如果想使用类似BCompare这种外部工具,Subversion 提供了一个命令  l(launch) 来打开精美的图形化合并工具。

如果想简单的选择文件版本,命令  mc (mine-conflict) 和  tc (theirs-conflict) 分别告诉 Subversion 选择用户的本地修改或从服务器收到的修改作为冲突 获胜的一方. 也可以使用“mine-full” 以及 “theirs-full”,不同的是, 前者两个命令会保留不产生冲突的本地修改和从服务器收到的修改。
其他的也一样,输入指令之后,是会有指示,自己慢慢尝试即可,并没有那么难。

提交修改

所有的问题都已经解决了,那么就可以提交了。 svn commit 把本地的所有修改发往仓库。提交时用户需要输入一段日志来描述本次修改,日志被附加到新的版本号上。
如果日志比较简短, 可以用选项 --message (-m) 直接在命令行上输入日志,如:
 svn commit -m "Corrected number of cheese slices"
如果把日志写到了某个文本文件中,可以通过选项 --file (-F) 实现,提交时直接从该文件中读取日志,如:
svn commit -F logmsg
如果用户在提交时没有指定选项 --message (-m) 或 --file (-F),Subversion 就会自动打开用户指定的编辑器来编写日志
在大部分情况下, Subversion 的日常使用就是目前所介绍的这些命令,下面我们还将 会介绍几个较常用到的命令。


他常用指令

svn log 默认按照时间逆序来打印消息
svn log <path> 查看当前目录或者当前文件的日志
svn log -r <versionNum> 显示当前版本号的日志
svn log -r <startVersionNum> <endVersionNum> 显示版本号区间的日志

svn cleanup 清理工作副本,如工作副本中的某些部分是被 “锁住” 的,执行该指令就可以解决。 

svn info 用于查询当前项目的svn信息,包含修改者路径信息等。

问题:为什么 svn log 没有显示我刚提交的日志?
如果在提交之后马上不带参数地执行 svn log,会发现输出的日志消息中没有包含最近的几次提交, 这种情况是由 svn commit 和 svn log 的共同作用的结果。首先,用户向仓库提交修改时, svn 只更新了被提交的文件和目录的版本号, 所以父目录依然是较旧的版本号。svn log 默认从目录的当前版本号开始获取历史消息,所以用户就看不到刚提交的日志。解决办法是用 svn update 更新工作副本, 或通过选项 --revision (-r) 显式地向 svn log 传递一个版本号。


好了,基本的使用就介绍到这里了。其实这算是摘抄,几乎是官方文档的介绍,只是太繁琐了,自己总结下。如果想详细查看,可以自行去官网查看哦。


参考:http://svnbook.red-bean.com/nightly/zh/svn-book.html#svn.tour.cycle.examine

猜你喜欢

转载自blog.csdn.net/pzm1993/article/details/78898498