SVN基本工作流程
来源:互联网 发布:sai2 mac中文版下载 编辑:程序博客网 时间:2024/05/01 23:23
基本工作流程
Subversion有大量特性,选项,丰富多样,但在日常基本工作中,更可能的是你仅仅用到很少的几个。在本节,我们浏览一下你在日常工作中使用Subversion最常会作的事。
典型的工作流程看起来像这样:
更新你的工作副本
svn update
做修改
svn add
svn delete
svn copy
svn move
检查你的改动
svn status
svn diff
svn revert
合并别人的改动
svn merge
svn resolved
提交你的改动
svn commit
当你在一个团队中为一个项目工作时,你会想要更新你的工作拷贝来获取那些你上次更新以来其他开放人员对项目做的新改动。使用 svn update会使你的工作副本和资料库中最新的修订版同步。
$ svn updateU foo.cU bar.cUpdated to revision 2.
这种情况表明在你上一次更新后,别人检入了对foo.c
和 bar.c
的修改。 Subversion已经更新了你的工作副本,加入了那些改动。
让我们更仔细的查看一下svn update的输出。当服务器发送改动到你的工作副本时,会在每项前显示一个字母代码,让你知道Subversion 在同步你的工作副本时对它作了什么动作:
U foo
文件
foo
被(U
pdated)更新了(从服务器接受修改)。A foo
文件或目录
foo
被加到了(A
dded)你的工作副本中。D foo
文件或目录
foo
被从你的工作副本删除了(D
eleted)。R foo
你工作副本中的文件或目录
foo
被替换了(R
eplaced)。就是说,foo
被删除了,一个新的同名项被添加了。虽然它们名字相同,但是资料库认为他们是不同的对象并有不同的历史纪录。G foo
文件
foo
从资料库收到了修改,但是你的本地副本已经被你修改了。或者是因为这些修改不交叉,或者是因为修改完全相同, Subversion已经成功地,毫无问题地把资料库中的修改合并(merG
ed)了到了文件中。C foo
文件
foo
从服务器接收到了冲突(C
onflicting)的改动。来自服务器的改动和你对文件的改动有直接重叠。即使这样也不用急。这些交叠需要人来解决;在本章稍后我们会讨论这一点。
现在你可以开始工作,修改你的工作副本了。通常选择做一个(或一些)特定的修改,比如写一个新的特性,解决一个Bug等比较好。这时可能用到的Subversion的命令是:svn add, svn delete, svn copy, and svn move。然而,如果你仅仅编辑那些已经在Subversion中的文件,你可能直到提交都不需要这些命令。你可以在你的工作副本中做的修改:
- 文件修改
这是最简单的那种的修改。你不需要告诉Subversion你打算改一个文件;只要改就行了。Subversion能自动探测哪些文件被修改过了。
- 树修改
你可以让Subversion把文件和目录标记为将要删除,增加,复制,或移动。虽然这些修改在你的工作副本中立即生效,但是直到你提交它们才会发生在资料库里。
修改文件时,可以使用你的文本编辑器,字处理器,图像编辑程序,或者其他任何你通常使用的工具。Subversion处理二进制文件就像处理文本文件一样容易——也同样高效。
下面是对四个Subversion子命令的一个概述。这些命令是你在修改树时最常用的。(我们将稍后谈到 svn import 和 svn mkdir)
- svn add foo
使文件,目录或者符号连接
foo
预定将要被添加到资料库。在你下一次提交时,foo
将会成为它父目录的子项。注意:如果foo
是一个目录,所有在foo
下的东西都会被预定要添加。如果你只想添加foo
本身,要用--non-recursive
(-N
)开关。- svn delete foo
预定文件目录或者符号链接
foo
要从资料库删除。如果foo
是一个文件或者一个连接,它马上就从你的工作副本删除。如果foo
是一个目录,它不被删除,但是Subversion预定它要被删除。当你提交你的修改时,foo
会被从你的工作副本和资料库删除。 [1]- svn copy foo bar
创建
foo
的一个名为bar
的拷贝。bar
自动被预定添加。当bar
在下次提交中被添加时,他的复制历史被记录了(即记录它原本来自于foo
)。 svn copy不会创建中间目录。- svn move foo bar
这个命令和运行svn copy foo bar; svn delete foo完全一样。就是说,
bar
作为foo
的一个拷贝被预定添加,同时foo
被预定删除。 svn move不会创建中间目录。
一旦你完成了修改,你需要把它们提交到资料库,但是在这么做之前,看一下究竟那些地方被修改了通常是个好主意。经过提交前对修改的检查,你能写出更准确的日志信息。也可能你会发现你无意中修改了一个文件,从而有机会在提交前取消这些改动。另外,这是一个在发布前回顾和细查那些改动的好机会。你可以使用svn status,svn diff和 svn revert命令来仔细查看究竟做了那些修改。前两个命令用来发现你的工作副本中那些文件和目录修改了,第三个命令用来取消一些(或者全部)修改。
Subversion已经对帮助你完成这样的任务作了优化,可以在不和资料库通信的情况下完成很多工作。详细的说,对每个在.svn
区域中置于版本控制下的文件,你的工作副本会秘密缓存一个“原始”的拷贝。有了这个拷贝,Subversion可以很快地显示你的工作文件被怎样修改了,甚至允许你不连接资料库而撤销这些修改。
你可能用svn status比任何别的Subversion命令都要多。
如果你在你的工作副本的顶层目录执行不带参数的svn status命令,它会检测所有文件和树的修改。下面是一些不同的 svn status命令会返回的状态码的例子。(注意,#
后的文字不会被svn status打印)
L abc.c # svn has a lock in its .svn directory for abc.c M bar.c # the content in bar.c has local modifications M baz.c # baz.c has property but no content modificationsX 3rd_party # this dir is part of an externals definition? foo.o # svn doesn't manage foo.o! some_dir # svn manages this, but it's either missing or incomplete~ qux # versioned as file/dir/link, but type has changedI .screenrc # svn doesn't manage this, and is configured to ignore itA + moved_dir # added with history of where it came fromM + moved_dir/README # added with history and has local modificationsD stuff/fish.c # this file is scheduled for deletionA stuff/loot/bloo.h # this file is scheduled for additionC stuff/loot/lump.c # this file has conflicts from an update S stuff/squawk # this file or dir has been switched to a branch
在这个输出格式中,svn status打印出5列字符,跟着是几个空格符,跟着是一个文件或目录名。第一列表明了一个文件或目录和(或)它的内容的状态。会在这里打出的代码有:
A item
文件,目录或者符号连接
item
已经被预定要添加到资料库。C item
文件
item
处在冲突状态中。就是说,更新时从服务器接收到的改动和你对工作副本作的本地改动交叠了。你必须在把你的修改提交到资料库前解决这些冲突。D item
文件,目录或者符号连接
item
已经被预定要从资料库删除。M item
文件的
item
的内容已经被修改了。X item
目录
item
没有版本化,但和一个Subversion 外部定义相关。更多关于外部定义的知识,参见 ???.? item
文件,目录或者符号连接
item
没有被置于版本控制之下。你可以传递--quiet
(-q
)参数给svn status命令,或者在父目录上设置svn:ignore
属性,从而不显示这个问号。关于忽略文件的更多信息,参见???。! item
文件,目录或者符号连接
item
在版本控制中,但是被丢失了或者有些不完整。如果这个项被非Subversion命令删除会导致丢失。如果是一个目录, 如果你打断了一次检出或者更新,它可能会不完整。只要用svn update命令就可以从资料库中重新取回这个文件或目录,或者使用 svn revert file可以恢复一个丢失的文件。~ item
文件,目录或者符号连接
item
在资料库中是某种类型的对象,但是和你工作副本中的不是同一种。例如,可能Subversion资料库中有个文件, 但你没有使用svn delete 和 svn add 命令而在本地删除了它并创建了一个同名的目录,。I item
文件,目录或者符号连接
item
没有置于版本控制之下,Subversion被配置成在执行svn add,svn import和 svn status操作中忽略它。关于忽略文件的更多信息,参见???。注意,这个符号只有在你传递--no-ignore
选项给svn status时才显示,否则文件会被忽略,根本不列出来。
第二列表明了一个文件或目录的属性集的状态(更多的关于属性的信息参见???)。如果M
出现在第二列,表明属性集被修改了,否则会打印一个空白符。
第三列只可能显示空白符或一个L
,意味着Subversion已经在.svn
工作区里锁定了这个文件。如果你在一个正在执行svn commit 的目录下运行svn status,你会看到这个L
——可能这时你在编辑日志文件。如果Subversion没有在运行中,那大概是Subversion进程被中断了,锁需要用svn cleanup(本章稍后会更多涉及这个命令)来解除。
第四列只可能显示空白符或者一个+
,意味着这个文件或者目录被预定添加,或者被带着附加的历史修改。这通常发生在当你svn move 或 svn copy一个文件或目录时。如果你看到A +
,这意味着这一条目被预定带着历史纪录添加。它可能是一个文件,或者一个被复制目录的根。+
意味着这个是一个预定被添加的子树的一部分,就是说,它的父目录被复制了,它只是跟着一起走。 M +
意味着这个是一个预定被带着历史纪录添加的子树的一部分,同时 它有本地改动。当你提交时,首先父目录被带着历史纪录添加(复制),这意味着这个文件将自动出现在拷贝中。然后本地修改将被上载到拷贝中。
第五列只可能显示空白符,或者是一个S
。这表明这个文件或目录已经被从工作副本路径切换(使用 svn switch)到一个分支里。
如果你传递一个指定的路径给svn status,它将只给出关于这个条目的信息:
$ svn status stuff/fish.cD stuff/fish.c
svn status也有一个--verbose
(-v
)选项,它将显示你工作副本中 每一个条目的状态,即使它没有被修改。
$ svn status --verboseM 44 23 sally README 44 30 sally INSTALLM 44 20 harry bar.c 44 18 ira stuff 44 35 harry stuff/trout.cD 44 19 ira stuff/fish.c 44 21 sally stuff/thingsA 0 ? ? stuff/things/bloo.h 44 36 harry stuff/things/gloo.c
这是svn status输出的“长形式”。第一列仍旧一样,但是第二列显示的是这个条目的工作修订版。第三和第四列分别显示了本项上次被修改的修订版和谁修改了它。
上面这些对svn status的使用都不会连接资料库,它们仅在本地工作,只要比较.svn
目录中的元数据和工作副本中的数据。最后,有一个--show-updates
(-u
)选项,它连接资料库来添加关于哪些东西过时了的信息。
$ svn status --show-updates --verboseM * 44 23 sally READMEM 44 20 harry bar.c * 44 35 harry stuff/trout.cD 44 19 ira stuff/fish.cA 0 ? ? stuff/things/bloo.hStatus against revision: 46
注意:这两个星号表明,如果你这时执行svn update,你将接收到README
和 trout.c
的修改。这给了你一些很有用的信息——你将需要更新并得到服务器上的改动,否则资料库将拒绝你的提交,因为你的文件过时了(稍后有更多关于这个主题的信息)。
另一个检查你的修改的办法是使用svn diff命令。你能精确的发现你修改的东西,只要执行不带参数的svn diff,这将用标准化的diff格式打印文件改动: [2]
$ svn diffIndex: 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; }Index: README===================================================================--- README(revision 3)+++ README(working copy)@@ -193,3 +193,4 @@ +Note to self: pick up laundry.Index: stuff/fish.c===================================================================--- stuff/fish.c(revision 1)+++ stuff/fish.c(working copy)-Welcome to the file known as 'fish'.-Information on fish will be here soon.Index: stuff/things/bloo.h===================================================================--- stuff/things/bloo.h(revision 8)+++ stuff/things/bloo.h(working copy)+Here is a new file to describe+things about bloo.
svn diff命令通过比较你的工作文件和缓存在.svn
区中的“原始的” 拷贝来产生输出。预定要添加的文件被显示为所有文本都是新加的,预定要删除的文件被显示为所有文本都被删除。
输出以标准化 diff 格式输出。就是说:删除的行以-
开头,添加的行以+
开头。 svn diff也打印文件名和偏移量这样对patch程序有用的信息。这样使你能把diff输出重定向到一个文件中来产生“补丁(patch)”。
$ svn diff > patchfile
例如,在提交前,你可以用电子邮件把补丁文件发送给另一个开发者来检查或者测试。
现在假设你看到了以上的diff输出,而且察觉到你对README
的修改是错的;可能你不小心在你的编辑器里把文字输错了文件。
这是一个极好的使用svn revert的机会。
$ svn revert READMEReverted 'README'
Subversion用.svn
区里缓存的“原始的”文件覆盖文件,从而把它恢复到修改前的样子。但是也要注意到svn revert可以撤销任何 预定操作——例如,你可以决定你不想添加某个文件了:
$ svn status foo? foo$ svn add fooA foo$ svn revert fooReverted 'foo'$ svn status foo? foo
注意
svn revert ITEM
和从你的工作副本中删除ITEM
,然后执行svn update -r BASE ITEM
效果完全一样。然而,如果你要恢复一个文件,svn revert有一个非常值得注意的特性——它恢复文件不需要和资料库通信。
或者,可能你错误的把一个文件从版本控制中拿掉了:
$ svn status README README$ svn delete README D README$ svn revert READMEReverted 'README'$ svn status README README
我们已经看到svn status -u怎样预报冲突。设想你执行了svn update并看到一些有趣的现象:
$ svn updateU INSTALLG READMEC bar.cUpdated to revision 46.
标记U
和G
没有什么好关心的;这些文件干净利索的吸收了来自资料库的修改。标记为U
的文件没有本地修改,而是被资料库中的修改更新(U
pdated)了。G
代表合并(merG
ed),这意味着本地文件被修改了,但是来自于资料库的改动和本地修改不重叠。
但是C
代表冲突,这意味着来自服务器的修改和你的修改重叠了,现在你必须手工来选择它们。
任何冲突发生时,通常会有三样东西来帮助你注意到和解决这冲突:
Subversion在更新时打印
C
,并记录这个文件是处在冲突状态。如果Subversion认为这个文件可以被合并,它会放置一个conflict markers冲突标记——用来划定“边界”的特殊的字符串—— 到这个文件中,以使重叠区域可被看到。(Subversion使用
svn:mime-type
属性来决定一个文件是否能在上下文中基于行来合并。参见???)对每个冲突的文件,Subversion会在你的工作副本里放三个额外地没有版本化的文件。
filename.mine
这是在你更新工作副本前存在于你的工作副本中的文件——就是说,没有冲突标记。这个文件只有你最后的修改。(如果Subversion认为这个文件没法被合并,那么
.mine
文件不会被创建,反正它将和你的工作文件一样。)filename.rOLDREV
这是你更新工作副本前的
BASE
修订版的文件。就是说,在你做最后的编辑前检出的文件。filename.rNEWREV
这个是当你更新了你的工作副本时,Subversion客户程序刚刚从服务器接收到的文件。这个文件对应与资料库中的
HEAD
修订版。
这里
OLDREV
是在你.svn
的文件的修订版号,NEWREV
是资料库中HEAD
的修订版号。
例如,Sally修改了资料库中的文件sandwich.txt
。Harry刚修改了自己工作副本中的这个文件并且检入了它。 Sally在检入前更新她的工作副本并发现了一个冲突:
$ svn updateC sandwich.txtUpdated to revision 2.$ ls -1sandwich.txtsandwich.txt.minesandwich.txt.r1sandwich.txt.r2
这时,Subversion 将不允许你提交文件sandwich.txt
,直到三个临时文件被删除。
$ svn commit --message "Add a few more things"svn: Commit failed (details follow):svn: Aborting commit: '/home/sally/svn-work/sandwich.txt' remains in conflict
如果你发现一个冲突,你需要做下面三件事之一:
“手工”合并冲突的文本(检查并编辑文件中的冲突标记)。
用临时文件中的某个覆盖你的工作文件。
执行svn revert <filename>来扔掉你的所有本地修改。
一旦你解决了冲突,你要执行svn resolved让Subversion知道。这个命令删除那三个临时文件并让Subversion不再认为那个文件在冲突状态。 [3]
$ svn resolved sandwich.txtResolved conflicted state of 'sandwich.txt'
当你第一次尝试的时候,手动合并冲突可能很难,但在有了些实践后,它就易如反掌了。
这儿有个例子。由于沟通不好,你和你的合作者Sally,同时编辑了文件sandwich.txt
。Sally 提交了它的修改,当你更新工作副本时,你发现一个冲突。我们将不得不比编辑sandwich.txt
来解决冲突。首先,我们来看一下文件:
$ cat sandwich.txtTop piece of breadMayonnaiseLettuceTomatoProvolone<<<<<<< .mineSalamiMortadellaProsciutto=======SauerkrautGrilled Chicken>>>>>>> .r2Creole MustardBottom piece of bread
由小于号,等号和大于号组成的字符串就是冲突标记,他们不是真正冲突数据的一部份。你只要确认在下次提交前从文件中删除他们。在头两个标记行之间的文字是冲突区域里属于你的修改的部分:
<<<<<<< .mineSalamiMortadellaProsciutto=======
在第二和第三个标记行之间的文字来自Sally的提交:
=======SauerkrautGrilled Chicken>>>>>>> .r2
通常,你不会只是想删除冲突标记和Sally的修改——当三明治送达但不是她想要的那种时她会非常吃惊的—— 因此,这是你应该拿起电话或者走过去,向Sally解释不可能从意大利熟食店买到泡菜。[4] 一旦你们在修改上达成一致,你可以检入了,编辑你的文件并且删除冲突标记。
Top piece of breadMayonnaiseLettuceTomatoProvoloneSalamiMortadellaProsciuttoCreole MustardBottom piece of bread
现在,执行svn resolved,然后你就可以提交你的修改了:
$ svn resolved sandwich.txt$ svn commit -m "Go ahead and use my sandwich, discarding Sally's edits."
记住,如果你编辑冲突文件时一时糊涂了,你总是可以参考Subversion在工作副本中为你创建的三个文件 ——包括了你更新前的文件。你甚至能用第三方的交互式合并工具检查这三个文件。
如果你发现一个冲突并决定放弃你的修改,你可以简单的用Subversion创建的临时文件之一覆盖你工作副本中的文件。
$ svn updateC sandwich.txtUpdated to revision 2.$ ls sandwich.*sandwich.txt sandwich.txt.mine sandwich.txt.r2 sandwich.txt.r1$ cp sandwich.txt.r2 sandwich.txt$ svn resolved sandwich.txt
如果你发现一个冲突,检查后决定你要放弃你的修改并重新编辑文件,只要撤回你的修改:
$ svn revert sandwich.txtReverted 'sandwich.txt'$ ls sandwich.*sandwich.txt
注意,当你恢复一个冲突文件时,你不一定要执行svn resolved。
现在你准备好检入你的修改了。注意svn resolved不像我们在本章介绍过的其他命令,它总是需要一个参数。在任何情况下,你都要小心,只在你确定你已经解决了冲突时才运行svn resolved,一旦临时文件被删除了,即使文件还包含冲突标记,Subversion也允许你提交它。
终于!你的编辑完成了,你已经合并了所有来自服务器的修改,你已经做好把你的修改提交到资料库的准备了。
svn commit把你的所有修改发送到资料库。当你提交一个修改,你要提供一个日志消息来描述你的修改。你的日志消息会被附加到你创建的新修订版上。如果你的日志消息简短,你可以使用--message
(或 -m
)在命令行中提供:
$ svn commit --message "Corrected number of cheese slices."Sending sandwich.txtTransmitting file data .Committed revision 3.
然而,如果在你工作时以已经编写了日志消息,你可以告诉Subversion从一个文件来得到消息,这要用--file
选项传递文件名:
$ svn commit --file logmsg Sending sandwich.txtTransmitting file data .Committed revision 4.
如果你既没有指定--message
,也没有指定--file
,Subversion会自动运行你喜好的编辑器(参见???中editor-cmd
一节)来让你编写一个日志。
提示
如果你在你的编辑器中写提交消息时决定取消你的提交,你只要退出你的编辑器而不保存修改就行了。如果你已经保存了提交消息,只要删除文字再次保存。
$ svn commitWaiting for Emacs...DoneLog message unchanged or not specifieda)bort, c)ontinue, e)dita$
资料库不知道也不关心你的提交作为一个整体是否有意义;它只检查确认在你没有看资料库时,其他人没有修改过你修改了的那些文件。如果有人这么做了,整个提交会失败,并有一个消息通知你,你的某个或某些文件过时了。
$ svn commit --message "Add another rule"Sending rules.txtsvn: Commit failed (details follow):svn: Out of date: 'rules.txt' in transaction 'g'
这时,你需要运行svn update,处理更新结果中的所有合并和冲突,然后再次尝试提交。
到这里已经探讨了使用Subversion的基本工作流程。Subversion有很多别的特性,你可用它们来管理的你的资料库和工作副本,但即时只使用我们到本章这里为止讨论过的命令,你也能很轻松的工作。
[1] 当然,没有什么会被从资料库完全删除——仅仅是从资料库的HEAD
修订版删除了。你可以取回所有你删除的东西,只要检出(或更新你的工作副本)你做删除前的一个修订版就行了。
[2] Subversion使用内置的diff引擎,缺省情况下以标准化diff格式输出。如果你想让diff用不同的格式输出,可以指定一个外部的diff 程序,这需要使用--diff-cmd
选项,并用--extensions
来传递任何你希望的标志。例如,要检查文件foo.c
本地差别,忽略空格,使用上下文输出格式,可使用这样的命令svn diff --diff-cmd /usr/bin/diff --extensions '-bc' foo.c。
[3] 你可以自己删掉那些临时文件,但既然Subversion能帮你做,你何必自己做呢?我们认为不必。
[4] And if you ask them for it, they may very well ride you out of town on a rail.
- SVN基本工作流程
- SVN 工作流程模型
- struts基本工作流程
- Repo基本工作流程
- STRUTS基本工作流程
- STRUTS基本工作流程
- Git --基本工作流程
- Git基本工作流程
- Mapreduce基本工作流程
- SVN的基本操作流程
- SVN 基本的工作循环
- OpenGL的基本工作流程
- 搜索引擎的基本工作流程
- Git 基本的工作流程
- Git基本的工作流程
- Hibernate的基本工作流程
- git基本的工作流程
- web的基本工作流程
- IIS 6.0 不能处理未知的 MIME 类
- 常用oracle 时间加减问题
- Web.py对模板传值的一个技巧
- c++的几个核心函数说明
- Scripting the Terminal Services Advanced Client
- SVN基本工作流程
- Iptables+NAT
- Asp.net"页面加载中"效果实现
- SERIAL PORT ABCs
- 在Glassfish中进行EJB调用的几种场景
- LINUX的目录树
- Java中的事务处理(1)
- 設計模式學習第一篇
- 除了现实还是现实······