Subversion 学习——分支功能

本文详细介绍SVN中分支(branch)与合并(merge)的基本概念、常用命令及具体操作流程。包括如何创建分支、切换分支、同步更新、解决冲突、预览合并信息等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分支与合并

一般来说一个SVN项目的路径为

ProjectName

Trunk

Branches

一般来说Trunk放的是工作的主目录,而branches放的是分支

$ 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.

这是从client创建branch的copy,但是很慢,不要这么做,还是在server上直接copy

Cheap Copy

在server的repository中的svn copy是一种cheap copy,指的是时间少,不占空间,因为SVN的copy往往是建立一种hard link而不是复制黏贴file

分支历史

使用svn log -v integer.c命令查看分支文件的历史时,可以看到之前在trunk目录下时的历史,包括创建分支的步骤

changeset

在SVN中的定义,认为changeset是指一次commit所产生的修改的list,每次commit会产生一个新的revision ID,这个ID N与N-1之间的区别就是一个changeset,SVN在merge的时候可以通过传递revision ID来merge(-c 9238)这时候就会把9238这个changeset merge到你的branch中

把/trunk目录下的更新,merge到branch中

命令格式svn merge URL

$ pwd

/home/user/my-calc-branch

$ svn merge ^/trunk

--- Merging r345 through r356 into '.':

U button.c

U integer.c

这里成功的前提是,没有conflict

同时通配符^是在1.6时引入的

将branch content修改提交到trunk中

1.svn update

2.svn merge--reintegrate^/trunk #将主目录的更新merge到branch

3.测试

4.简单使用svn commit –m “comments”命令

reintegrate选项,用来标记trunk的lastest version与branch中的lastest version的差别,也就是你的branch到底修改了哪些,用来在commit的时候起作用

删除branch

在merge――reintegrate之后,可以删除当前的branch,如果以后需要,可以通过svn log整个/branch目录来查看历史,找到删除的branch,恢复

继续在branch上工作

在1.5SVN中,一旦进行了merge - -reintegrate之后,branch就不可用了,因为branch不能在从trunk获得更新,所以最好的办法就是删除,然后重新创建一个branch

$ svndeletehttp://svn.example.com/repos/calc/branches/my-calc-branch -m "Remove my-calc-branch."

Committed revision 392.

$svncopy

http://svn.example.com/repos/calc/trunkhttp://svn.example.com/repos/calc/branches/new-branch-m "Create a new branch from trunk."

Committed revision 393.

$ cd my-calc-branch

$ svnswitch^/branches/new-branch

Updated to revision 393.

注意最后的svn switch命令

合并信息预览

可以在运行svn merge之前,预览所要merge的信息,包括revision ID等,关于所有的merge信息,会被SVN存放在svn:mergeinfo这个property中,运行

svnmergeinfo^/trunk TARGET

命令可以看到要进行merge的revision ID,同时TARGET表示merge到的目录,可以省略,省略之后就是当前目录

同时可以使用- -dry-run选项,来提前查看要merge的文件的状态,简单说就是进行了merge以后,运行svn status显示的信息,可以通过命令svn merge URL - -dry-run来进行查看

取消修改

在SVN中,如果觉得某个revision做的修改wrong,希望取消,可以使用

svn merge –r 302:303

svn merge –c 303

命令,这里-r表示revision ID的范围,-c直接就是回到303之前

同时,修改完以后,可以通过svn status, svn diff来确认,然后svn commit

这里的修改,只是把正确的内容放到最新的revision中,而不是删除以前的revision,SVN默认是不删除任何内容的,同时如果你去get那个错误的revision,它同样存在

恢复删除的文件/目录

作为SVN来说,最大的好处是,所有的操作都被记录,而且可以查看,找到,进行你要的处理,想要恢复被删掉的文件,可以使用两种方法。

不论哪种,先要找到文件

使用svn log –v命令,-v(- -verbose)选项会显示当前目录下的所有历史修改

然后找到删除这个文件的信息,有那次的revisionID ,以及那次修改的所有内容

这时候恢复:

1.使用svn merge –c命令,但是这个命令会把那次所有的修改回退,这不是你所要的,当然你可以使用svn revert FILE来取消不要的,但是一旦文件很多,就很麻烦

2.使用svn copy ,

使用这个命令,需要知道SVN的一个概念,就是所有版本中的所有文件都可以使用一个方式来唯一表达,这个方式就是PEG,分为2个部分,1是path,2是revision ID

比如:^/trunk/real.c@809指的是在trunk目录下的real.c文件,在809的版本

这时候可以通过svn copy^/trunk/real.c@809./real.c命令来恢复real.c文件到当前目录

摘录合并

指的是,选取你需要的changeset来对branch的content进行merge,使用svn merge

-c revisionID命令来做到,(- - change)

同时在merge之前,可以通过svn diff –c revisionID来对要进行merge的内容的查看

同时你进行了merge之后,以后如果在进行完全的merge,这次merge的内容将被跳过

完整的合并语法

无论是使用svn merge还是svn merge –c都不是完整的merge语法

完整的merge语法,包含3个部分:

1.Merge的revision的起始版本

2.Merge的revision的最终版本

3.Merge的TARGET

简单的说,就是使用–r选项,当然也可以使用PEG模式(URL@REV

如:

$ 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:200http://svn.example.com/repos/trunk

#省略了当前的工作目录TARGET

没有svn:mergeinfo的合并

svn:mergeinfo是非常重要的SVN property,关系到SVN能否智慧的merge信息

但是在3中情况下,SVN不会创建或设置svn:mergeinfo的信息

1.Merge的源,是与当前TARGET完全无关的,没有共同历史的

2.Merge的源,是其他库的源

3.使用了- -ignore-ancestry (忽略祖先)

合并冲突

Merge出现conflict的时候,在本地会产生3个文件:

filename.working,

filename.left

filename.right

left,right表示的是合并的方向,left应该指的是源,right是TARGET上old文件

合并历史查看

在merge之后,通常可以使用svn log -v来查看TARGET的修改日志,但是日志上没有区分到底是merge的内容,还是自己修改commit的内容,所以使用–g (- -use-merge-history)选项来显示,merge的历史svn log –v –r 390 –g,这个命令显示的包括在trunk目录下的历史,可以让用户来追踪

效果如下

$ svn log -v -r 390

------------------------------------------------------------------------

r390 | user | 2002-11-22 11:01:57 -0600 (Fri, 22 Nov 2002) | 1 line

Changed paths:

M /branches/my-calc-branch/button.c

M /branches/my-calc-branch/README

Final merge of trunk changes to my-calc-branch.

$ svn log -v -r 390 -g

------------------------------------------------------------------------

r390 | user | 2002-11-22 11:01:57 -0600 (Fri, 22 Nov 2002) | 1 line

Changed paths:

M /branches/my-calc-branch/button.c

M /branches/my-calc-branch/README

Final merge of trunk changes to my-calc-branch.

r383 | sally | 2002-11-21 03:19:00 -0600 (Thu, 21 Nov 2002) | 2 lines

Changed paths:

M /branches/my-calc-branch/button.c

Merged via: r390

Fix inverse graphic error on button.

------------------------------------------------------------------------

r382 | sally | 2002-11-20 16:57:06 -0600 (Wed, 20 Nov 2002) | 2 lines

Changed paths:

M /branches/my-calc-branch/README

Merged via: r390

Document my last fix in README.

同时在svn blame命令中,也需要用到-g选项

效果如下:

$ svn blame button.c

390 user retval = inverse_func(button, path);

390 user return retval;

390 user }

$ svn blame button.c -g

…G

383 sally retval = inverse_func(button, path);

G 383 sally return retval;

390 user }

使用了-g就可以知道到底谁提交的修改

关于祖先(ancestry)

简单来说,一个file的revision 99版本是100版本的祖先,但是当101中删除了这个文件,然后102中创建ADD了一个新的同名文件时,99不是102的祖先

祖先的概念,导致了svn diff与svn merge的一个区别

对于svn diff来说不关心祖先,只关心path,也就是说svn diff –r 99 –r 102之间比较就是file的line-by-line的比较

而svn merge时,就会提醒,一个file要被删除,一个新的file要ADD

同样对于svn commit也是一样的道理

提供- -ignore-ancestry选项,就是忽略祖先关系,像svn diff那样比较

使用分支

在SVN上,svn copy创建的branch在本地使用,1是可以通过checkout来得到,2可能因为branch与trunk十分接近,同时又暂时不需要在trunk上工作,可以用svn switch URL切换到

Branch分支上工作

使用svn info | grep “URL”,可以看到当前工作目录的URL

同时对于svn switch不仅仅可以swith整个working copy,还可以switch某个subdictionary或者某个file,这是一旦switch之后本地的工作副本就是一个mix的版本(碰到的情况,为了测试branch的某个功能在trunk下的工作情况),这个mix的版本一样可以update,commit,同时update与commit的对象,都会自动区分,来自branch的subdictionary与file会得到来自branch的update,同时commit到branch

关于TAG

在SVN中tag与branch并没有区别定义,他们之间的区分是人为的概念。TAG也是使用svn copy创建的一个branch,唯一的不同是,不会再对这个branch进行修改提交的情况。

分支与合并命令

Action

Command

创建一个分支或标签

svn copy URL1 URL2

切换工作副本到分支或标签

svn switch URL1

将分支与主干同步

svn merge trunkURL ; svn commit

参见合并历史或适当修改集

svn mergeinfo SOUCE TARGET

合并分支到主干

svn merge - -reintegrate branchURL; svn commit

复制特定的修改

svn merge –c REV URL; svn commit;

合并一个范围的修改

svn merge –r REV1:REV2 URL ; svn commit;

让自动合并跳过一个修改

svn merge –c REV - -record-only URL; svn commit;

预览合并

svn merge URL - -dry-run

丢弃合并结果

svn revert –R .

从历史复活某些事物

svn copy PATH@REV localPATH

撤销已提交的修改

svn merge –c REV URL; svn commit;

感知合并的检查历史

svn log –g; svn blame –g;

从工作副本创建一个标签

svn copy . targetURL

重新整理分支或标签

svn mv URL1 URL2

删除分支或标签

svn rm URL

原作:http://patrick002.iteye.com/blog/1113457

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值