svn 实例操作1

我打算一口气讲完SVN的使用,所以,在看之前呢,请先深深的吸一口气(怎么听着像黑龙公主),当然吸完后还是要呼出来的。不要憋着了。

我们可能希望一来就直接操作。列出一堆命令。详细的命令参数等信息,我们都可以加入 –help 选项获取,下面不会详细介绍。除非必要。现在先看下面的例子:

$svn –help

usage: svn <subcommand> [options] [args]

Subversion command-line client, version 1.6.12.

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/

好了,什么都出来了。一大堆信息。慢慢读吧。可是这样的方式,对我们使用SVN并无指导意义。什么时候用什么命令? 下面就来说一下SVN的基本使用,在此之前,还有两个重要的东西需要理解。

SVN 除了可以让你追溯历史,还有一个重要的功能,便是多人协作。我们要解决的问题不仅仅是可以从历史中恢复。还有如果多人同时修改一个文件,那么该以谁的为主呢?

所以在SVN中,我们有两种使用模式:

Lock-Modify-Unlock

简单的说就是,给需要修改的文件加锁,然后修改,然后解锁。

这是一个很好的办法。但是如果一个文件被锁住了,那么其他人就不能修改了。而此时如果是我在修改文件头,而你需要修改文件末尾的话,你也只能等我修改完。这样是很浪费你的时间的。所以我们又有另外一种模式。

Copy-Modify-Merge

这是一种很高级的模式,从库中拷贝一份,修改,然后根据拷贝的和库中的不同,在合并。为什么说高级呢,因为合并是一个很复杂的过程。很可能失败。但是这种方法却尽可能使大家不受影响。例如你和我同时修改一个文件,我改文件头,你改文件尾,然后一提交,就给合成一份了。不会互相打扰。事实上问题比这复杂的多。

好了,说了这么多废话。我们可以正式开始了。

虽然一般情况,我们是不用自己去创建一个SVN库的,现在为了说明流畅,我们从创建一个库开始。

$svnadmin create  /var/idp/repos

于是我们创建了一个SVN库。到下面看看

$ls /var/idp/repos

conf  db  format  hooks  locks  README.txt

我们的库就创建好了。这里不多说, svnadmin是一个高级命令,我们基本用不到。

导入需要管理的文件:

$svn import /home/madic/code file:///var/idp/repos -m “init code”

Adding         /home/madic/code/signo

Adding         /home/madic/code/signo/sigset.c

Adding  (bin)  /home/madic/code/signo/wait

Adding         /home/madic/code/signo/wait.c

Committed revision 1.

这里版本变为1,初始版本为0。  每次对库的操作改变,都会产生一个新的版本。版本是我们追溯历史的一个索引。在版本管理中非常重要。当前库中最新的版本可以用HEAD表示。HEAD版也就是库中最新版本。

我们把 /home/madic/code 文件下的文件目录都导入了svn库,从此,他们就被时光机管理,数据永不丢失(当然你干掉时光机,数据还是会丢失的)。

注意 (bin) 表示这是一个二进制文件,非文本文件。

除了import 外,我们还可以用 svn add 添加文件。

使用list命令查看库中文件

$svn  list  file:///var/idp/repos

signo/

signo/sigset.c

signo/wait

signo/wait.c

现在,我们开始工作了。那么,就使用 CMC(Copy-Modify-Merge)模式吧。

如何创建一个Working Copy 呢?看:

$svn checkout file:///var/idp/repos  /home/madic/code_svn

A    /home/madic/code_svn/signo

A    /home/madic/code_svn/signo/sigset.c

A    /home/madic/code_svn/signo/wait

A    /home/madic/code_svn/signo/wait.c

Checked out revision 1.

恭喜我们现在拥有一个Working Copy了,你就在这个WorkingCopy中折腾吧,只要不提交,那么对库来说就没有任何影响。就算你用了 rm 不小心删除了某个文件,不用着急。使用update便可以找回。

$svn update

svn update

Restored ‘main.c’

At revision 1.

这里,我们删掉 main.c 然后到WC 下,执行 svn update 命令,就找回main.c了。

在Working Copy 目录中,Subversion如何知道文件的情况呢,其实这些都是 .svn的功劳。每个SVN管理的WC中,都会有一个隐藏的文件夹,.svn

$ls -la .svn

drwxr-xr-x  6 madic madic 4096 2011-07-26 11:00 .svn

如果不小心误删除,也可以用svn update恢复。

接下来,我们开始正常的编辑文件。编辑之前,已定要使用svn update 来确保你编辑的文件是最新的。如果不是最新的,那么这个文件就是 Out-of-date了,此时你的编辑就不能被提交到库中。编辑时,你不必使用svn的命令了。你可以用任何编辑器编辑文件。当你编辑完成后保存。

$svn status -q

M       readme.txt

这个M表示此文件被修改了。于是我们需要把她提交到库,这样别人才能看到我修改的东西。

$svn commit -m “我修改了文件内容” readme.txt

svn commit -m “modify” readme.txt

Sending        readme.txt

Transmitting file data .

Committed revision 8.

文件被提交,版本更新到8.

这样,我们就完成了一个最基本的SVN操作流程。也许如果没有什么大事,我们就到此结束了。难道还有什么问题吗?

上面提到,我们在修改的同时,可能别人也在修改。所以要尽量在每次修改的时候,保持我们的WC和库中的是同步的,也就是最新的。我们使用svn update来使自己的working copy是最新的。我们也可以用一个新的命令来看WC的状态。

$svn status -u -v readme.txt

M                8        8  madic        readme.txt

M     *          8        3  madic        foo.c

我们看到readme.txt 目前是M(modify)状态,说明此文件被改了。当前版本和最新版本都是8 ,用户是madic。

而foo.c 多了个星号,这表明foo.c 已经out-of-date 了。也就是说,我们在修改的版本,已经不是最新的了。在我们修改的时候,已经有人提交了新的版本。

除了 M表示修改,还有 U表示更新,D表示删除,A 表示新增, C表示冲突。

有时候有两个MM,此时并非表示美眉,而是文件的内容和属性都被改变了。

同样UU表示属性和内容都更新了。

所以,在我们提交以后,并非就结束了,此时,我们需要查看一下状态。如果有文件处于C状态,那么说明我们遇到麻烦了。因为C表示冲突了,一定是某个人和我们在改同一个地方。

这时,最好的办法是直接找到和我们冲突的修改人。然后沟通吧。是你死还是我亡。冲突实际上是在svn update的时候发生的。由于我编辑的太久了,你已经提交了一个新版本,我提交的时候,提示 out-of-date了,于是我svn update,冲突出现:

$ svn update

Conflict discovered in ‘readme.txt’.

Select: (p) postpone, (df) diff-full, (e) edit,

        (mc) mine-conflict, (tc) theirs-conflict,

        (s) show all options:

这时几个选择出现了,postpone 的意思是暂时推后处理,我可能要和那个和我冲突的家伙商量一番。 diff-full,则是比比看,到底什么地方冲突了。edit,修改冲突合并的文件。 mc,这个霸道,直接用我的。 tc , 底气不足,还是用别人修改的吧。我们一切三思而后行,所以选择了p,然后在看看文件目录下有什么。

多了三个文件:

readme.txt.mine  readme.txt.r9  readme.txt  readme.txt.r8

我们来说说这三个文件:readme.txt.mine 后最 mine是本地最新的。

readme.txt.r9 很明显,是版本9的,这个版本正式库中最新的版本。

readme.txt.r8  这个版本是库中最新的版本的前一版本。

我们来看一下,现在的readme.txt

$cat readme.txt

<<<<<<< .mine

hi

=======

hello

>>>>>>> .r9

很明显,我的版本中是hi ,而r9 的是hello。

好吧,我明白了。现在假设我们很明白,或者已经和发生冲突的文件的编辑同事商量好了。我们就要解决冲突了。

首先,上面说的三个文件,如果存在,我们就提交不了。

其次,需要选择一个解决方法。

$svn resolve –accepting working reademe.txt

svn resolve 是解决冲突的命令。解决的方法由–accepting 选项决定。

base  恢复到冲突前的一个版本。

mine-full  恢复到以我的修改为主的版本

their-full  恢复到库中最新版本

working  手动解决

所以,上面的那句命令其实还有问题,因为我们还没有手工修改文件。

于是我们打开readme.txt,去掉哪些冲突标识

<<<<<<< .mine

hi

=======

hello

>>>>>>> .r9

修改为

No hi no hello

然后保存readme.txt

在使用

$svn resolve –accepting working reademe.txt

注意,这一步以后,并没有真正完成冲突解决。

$svn commit -m “conflict resole”

Sending        readme.txt

Transmitting file data .

Committed revision 10.

这次提交OK。冲突至此解决。

有时候,我们编写到一半发现有人提交了更新或者是越写越乱,我们想放弃这次编辑,恢复到上一个版本,当然,我们可以直接rm掉,然后update,我们也可以这样:

$svn revert readme.txt

Reverted ‘readme.txt’

问题解决以后,请使用svn status 查看一下状态,是否正常了。

$svn status -vu readme.txt

                10       10 yinshaoxin   readme.txt

Status against revision:     10

没有什么M,C,* ,D, ? 这些,说明状态正常。

对于我们操作的这些,我们可以通过历史svn log来查看状态。

$svn log

r9 | yinshaoxin | 2011-07-26 13:39:12 +0800 (Tue, 26 Jul 2011) | 1 line

shaoxin

————————————————————————

r8 | madic | 2011-07-26 11:12:47 +0800 (Tue, 26 Jul 2011) | 1 line

modify

————————————————————————

r7 | madic | 2011-07-26 09:35:51 +0800 (Tue, 26 Jul 2011) | 1 line

code

————————————————————————

r6 | madic | 2011-07-20 15:43:52 +0800 (Wed, 20 Jul 2011) | 1 line

pa

————————————————————————

r5 | madic | 2011-07-20 15:42:19 +0800 (Wed, 20 Jul 2011) | 1 line

p

————————————————————————

r4 | madic | 2011-07-20 10:40:03 +0800 (Wed, 20 Jul 2011) | 1 line

dir

————————————————————————

r3 | madic | 2011-07-19 14:01:49 +0800 (Tue, 19 Jul 2011) | 1 line

keywords

————————————————————————

r2 | madic | 2011-07-19 13:58:24 +0800 (Tue, 19 Jul 2011) | 1 line

new test

————————————————————————

r1 | madic | 2011-07-15 16:56:05 +0800 (Fri, 15 Jul 2011) | 1 line

ci chage

————————————————————————

天哪,所有的svn日志都显示出来了。我们可以使用r来确定一个范围。

这就是时光机的历史查看了。来吧,想看哪一个版本的。

$svn log -r 5:9

————————————————————————

r5 | madic | 2011-07-20 15:42:19 +0800 (Wed, 20 Jul 2011) | 1 line

p

————————————————————————

r6 | madic | 2011-07-20 15:43:52 +0800 (Wed, 20 Jul 2011) | 1 line

pa

————————————————————————

r7 | madic | 2011-07-26 09:35:51 +0800 (Tue, 26 Jul 2011) | 1 line

code

————————————————————————

r8 | madic | 2011-07-26 11:12:47 +0800 (Tue, 26 Jul 2011) | 1 line

modify

————————————————————————

r9 | yinshaoxin | 2011-07-26 13:39:12 +0800 (Tue, 26 Jul 2011) | 1 line

shaoxin

————————————————————————

注意  -r 5:9  和 -r 9:5 是不同的顺序显示。

当然也可以指定一个文件的版本日志。

使用log注意,当你提交一个版本后,log并看不到这个日志。

因为 commit 和 update是独立的。commit并不更新本地版本。我们只有使用 update以后,在使用log则可以看到。

还有,如果你使用svn log 不指定路径的话,那么默认的是当前的目录。这样,对于其他目录的log,我们只有一条空日志。

$——————————————-

最后不要像我一样,日志都是乱七八糟,请重视日志,因为在以后查找问题梳理版本变化的时候,会对你有很大帮助。

好了,从现在开始,你已经基本掌握SVN的用法了。如果具体命令参数不会用,请使用 help 。

如果你想了解的更多一点,那么我们继续看下一章。

转自:http://airu.iteye.com/blog/1142301