创建自己的版本库
svnadmin create –fs-type fsfs /home/lmzhang/myrepos.
svn ci -m “”
关于内置版本号.
HEAD - 最新版本号.
BASE - 当前工作版本的未修改版本.
COMMITTED - BASE - 1
PREV - COMMITTED - 1
svn merge 的作用可以用语在任何两个版本之间的差异合并到某个工作版本的功能.
语法如下
举例来说我有一个工作copy,内有一个1.txt 当前版本号是1.
内容是 first.
然后我添加为 first second. svn ci -m “”.
然后我执行 svn merge -r HEAD:PREV 1.txt , svn将比较 HEAD版本和PREV版本的内容差异,然后将这个差异合并到 当前路径下的1.txt , 由于差异是减少了 second , 因此相当于回到了 版本1.
svn merge的语法允许非常灵活的指定参数,如下是一些例子:
$ svn merge http://svn.example.com/repos/branch1@150 \
http://svn.example.com/repos/branch2@212 \
my-working-copy
$ svn merge -r 100:200 http://svn.example.com/repos/trunk my-working-copy
$ svn merge -r 100:200 http://svn.example.com/repos/trunk
第一种语法使用URL@REV的形式直接列出了所有参数,第二种语法可以用来作为比较同一个URL的不同版本的简略写法,最后一种语法表示工作拷贝是可选的,如果省略,默认是当前目录。
svn 的分支创建倒是很容易.
svn copy from to , 那么to就成为了from的一个copy,在svn的概念中就是分支或者tag.
问题在于合并.
svn 的概念中,分之合并实际上是将某个分之某个版本到另外一个版本之间的变化合并到某个目录的概念.
比如 分支 b-1 从开始分支的版本 4 , 到做了修改后的版本 9 . 想合并到主干上.
// 下面说明了,为什么要用上面这种做法,仅仅比较带合并的分支的信息.
(
但是要哪两个树进行比较呢?乍一看,回答很明确,只要比较最新的主干与分支。但是你要意识到—这个想法是错误的,伤害了许多新用户!因为svn merge的操作很像svn diff,比较最新的主干和分支树不仅仅会描述你在分支上所作的修改,这样的比较会展示太多的不同,不仅包括分支上的增加,也包括了主干上的删除操作,而这些删除根本就没有在分支上发生过。
)
另外通过同一分支上的版本间merge可以执行反向操作,比如版本5对于版本4的修改是完全错误的,那么可以通过 svn merge -r 5:4 file.cpp working-copy 来达到在working-copy 中取消这个修改.
反向操作另外一个作用,加入你删除了head版本中的test.cpp , 但是又想找回来,那么你可以 svn log -v 察看test.cpp 是什么时候被删除的., -r 10 , 上一个版本 8 . 那么可以执行如下
svn merger -r 10:8 file:///…/ working-copy 就还原了.
当然svn copy -r 也可以.
还有一种方式就是两个分支间直接进行合并.
另外merge 有一个有用的参数,–dry-run 表示仅仅模拟本次合并的效果,实际上并不生效.
举例来说
就表示将主干 v1 到分支b_1 v4 之间的差别进行列举合并到当前工作目录.
tag 本身和branch在svn 中的操方式是一样的,不过tag还有一个增强点,就是能够将当前工作目录直接进行tag.
update 状态
U foo
文件foo
更新了(从服务器收到修改)。
A foo
文件或目录foo
被添加到工作拷贝。
D foo
文件或目录foo
在工作拷贝被删除了。
R foo
文件或目录foo
在工作拷贝已经被替换了,这是说,foo
被删除,而一个新的同样名字的项目添加进来,它们具有同样的名字,但是版本库会把它们看作具备不同历史的不同对象。
G foo
文件foo
接收到版本库的更改,你的本地版本也已经修改,但改变没有互相影响,Subversion成功的将版本库和本地文件合并,没有发生任何问题。
C foo
文件foo
的修改与服务器冲突,服务器的修改与你的修改交迭在一起,不要恐慌,这种冲突需要人(你)来解决,我们在后面的章节讨论这种情况。
svn status
L some_dir # svn已经在.svn目录锁定了some_dir
M bar.c # bar.c的内容已经在本地修改过了
M baz.c # baz.c属性有修改,但没有内容修改
X 3rd_party # 这个目录是外部定义的一部分
? foo.o # svn并没有管理foo.o
! some_dir # svn管理这个,但它可能丢失或者不完
~ qux # 作为file/dir/link进行了版本控制,但类型已经改变
I .screenrc # svn不管理这个,配置确定要忽略它
A + moved_dir # 包含历史的添加,历史记录了它的来历
M + moved_dir/README # 包含历史的添加,并有了本地修改
D stuff/fish.c # 这个文件预定要删除
A stuff/loot/bloo.h # 这个文件预定要添加
C stuff/loot/lump.c # 这个文件在更新时发生冲突
C stuff/loot/glub.c # 文件在更新时发生属性冲突
R xyz.c # 这个文件预定要被替换
S stuff/squawk # 这个文件已经跳转到了分支
K dog.jpg # 文件在本地锁定;有锁定令牌
O cat.jpg # 文件在版本库被其他用户锁定
B bird.jpg # 文件本地锁定,但锁定发生错误
T fish.jpg # 文件本地锁定,但锁定丢失
第一列
A item
文件、目录或是符号链item
预定加入到版本库。
C item
文件item
发生冲突,在从服务器更新时与本地版本发生交迭,在你提交到版本库前,必须手工的解决冲突。
D item
文件、目录或是符号链item
预定从版本库中删除。
M item
文件item
的内容被修改了。
R item
文件、目录或是符号链item
预定将要替换版本库中的item
,这意味着这个对象首先要被删除,另外一个同名的对象将要被添加,所有的操作发生在一个修订版本。
X item
目录没有版本化,但是与Subversion的外部定义关联,关于外部定义,可以看“外部定义”一节。
? item
文件、目录或是符号链item
不在版本控制之下,你可以通过使用svn status的--quiet
(-q
)参数或父目录的svn:ignore
属性忽略这个问题,关于忽略文件的使用,见“svn:ignore
”一节。
! item
文件、目录或是符号链item
在版本控制之下,但是已经丢失或者不完整,这可能因为使用非Subversion命令删除造成的,如果是一个目录,有可能是检出或是更新时的中断造成的,使用svn update可以重新从版本库获得文件或者目录,也可以使用svn revert file恢复原来的文件。
~ item
文件、目录或是符号链item
在版本库已经存在,但你的工作拷贝中的是另一个。举一个例子,你删除了一个版本库的文件,新建了一个在原来的位置,而且整个过程中没有使用svn delete或是svn add。
I item
文件、目录或是符号链item
不在版本控制下,Subversion已经配置好了会在svn add、svn import和svn status命令忽略这个文件,关于忽略文件,见“svn:ignore
”一节。注意,这个符号只会在使用svn status的参数--no-ignore
时才会出现—否则这个文件会被忽略且不会显示!
第二列说明文件或目录的属性的状态(更多细节可以看“属性”一节),如果一个M
出现在第二列,说明属性被修改了,否则显示空白。
第三列只显示空白或者L
,L
表示Subversion已经锁定了这个目录的工作区域.svn
,当你的svn commit正在运行的时候—也许正在输入log信息,运行svn status你可以看到L
标记,如果这时候Subversion并没有运行,可以推测Subversion发生中断并且已经锁定,你必须运行svn cleanup来清除锁定(本节后面将有更多论述)。
第四列只会显示空白或+
,+
的意思是一个有附加历史信息的文件或目录预定添加或者修改到版本库,通常出现在svn move或是svn copy时,如果是看到A +
就是说要包含历史的增加,它可以是一个文件或是拷贝的根目录。+
表示它是即将包含历史增加到版本库的目录的一部分,也就是说他的父目录要拷贝,它只是跟着一起的。 M +
表示将要包含历史的增加,并且已经更改了。当你提交时,首先会随父目录进行包含历史的增加,然后本地的修改提交到更改后的版本
第五列只显示空白或是S
,表示这个目录或文件已经转到了一个分支下了(使用svn switch)。
svn status也有一个–verbose
(-v
)选项,它可以显示工作拷贝中的所有项目,即使没有改变过:
$ svn status --verbose
M 44 23 sally README
44 30 sally INSTALL
M 44 20 harry bar.c
44 18 ira stuff
44 35 harry stuff/trout.c
D 44 19 ira stuff/fish.c
44 21 sally stuff/things
A 0 ? ? stuff/things/bloo.h
44 36 harry stuff/things/gloo.c
第一列保持相同,第二列显示一个工作版本号,第三和第四列显示最后一次修改的版本号和修改人。
上面所有的svn status调用并没有联系版本库,只是与.svn
中的元数据进行比较的结果,最后,是–show-updates
(-u
)参数,它将会联系版本库为已经过时的数据添加新信息:
$ svn status --show-updates --verbose
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.h
Status against revision: 46
注意这两个星号:如果你现在执行svn update,你的README
和trout.c
会被更新,这告诉你许多有用的信息—你可以在提交之前,需要使用更新操作得到文件README
的更新,或者说文件已经过时,版本库会拒绝了你的提交。
输出的格式为统一区别格式(unified diff format),删除的行前面加一个-
,添加的行前面有一个+
,svn diff命令也打印文件名和打补丁需要的信息,所以你可以通过重定向一个区别文件来生成“补丁”:
$ svn diff > patchfile
举个例子,你可以把补丁文件发送邮件到其他开发者,在提交之前审核和测试。
如果你只是希望检查一个过去的版本而不希望察看它们的区别,使用svn cat:
$ svn cat --revision 2 rules.txt
Be kind to others
Freedom = Chocolate Ice Cream
Everything in moderation
Chew with your mouth open
$
你可以重定向输出到一个文件:
$ svn cat --revision 2 rules.txt > rules.txt.v2
除了以上的命令,你可以使用带参数--revision
的svn update和svn checkout来使整个工作拷贝“回到过去”[7]:
$ svn checkout --revision 1729 # Checks out a new working copy at r1729
…
$ svn update --revision 1729 # Updates an existing working copy to r1729
…
# 建立库
$ svnadmin create /usr/local/svn/newrepos
# 建立分支
建立一个备份只是传递两个目录参数到svn copy命令:
$ cd bigwc
$ svn copy trunk branches/my-calc-branch
$ svn status
A + branches/my-calc-branch
现在,我们必须告诉你建立分支最简单的方法:svn copy可以直接对两个URL操作。
$ svn copy http://svn.example.com/repos/calc/trunk \
http://svn.example.com/repos/calc/branches/my-calc-branch \
-m "Creating a private branch of /calc/trunk."
Committed revision 341.
锁定-修改-解锁问题
我们有两个共同工作者,Harry和Sally,他们想同时编辑版本库里的同一个文件,如果首先Harry保存它的修改,过了一会,Sally可能凑巧用自己的版本覆盖了这些文件,Harry的更改不会永远消失(因为系统记录了每次修改),Harry所有的修改不会出现在Sally的文件中,所以Harry的工作还是丢失了—至少是从最新的版本中丢失了—而且是意外的,这就是我们要明确避免的情况!
在这种情况下,我们应该明确对需要进行修改的目录进行锁定.
拷贝-修改-合并模型假定文件是可以根据上下文合并的:就是版本库的文件主要是以行为基础的文本文件(例如程序源代码)。但对于二进制格式,例如艺术品或声音,在这种情况下,十分有必要让用户轮流修改文件,如果没有线性的访问,有些人的许多工作就最终要被放弃。
copy-edit-merge
原文:http://www.alisdn.com/wordpress/?p=1381