Subversion 学习 四 分支功能

分支与合并

一般来说一个 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 创建 branchcopy ,但是很慢,不要这么做,还是在 server 上直接 copy

 

Cheap Copy

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

 

分支历史

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

 

changeset

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

 

/trunk 目录下的更新, mergebranch

命令格式 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 # 将主目录的更新 mergebranch

3.       测试

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

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

删除 branch

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

 

继续在 branch 上工作

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

 

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

Committed revision 392.

$svn copy

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

Committed revision 393.

 

$ cd my-calc-branch

$ svn switch ^/branches/new-branch

Updated to revision 393.

注意最后的 svn switch 命令

 

合并信息预览

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

  svn mergeinfo ^/trunk TARGET

命令可以看到要进行 mergerevision 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 中,而不是删除以前的 revisionSVN 默认是不删除任何内容的,同时如果你去 get 那个错误的 revision ,它同样存在

 

恢复删除的文件 / 目录

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

不论哪种,先要找到文件

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

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

这时候恢复:

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

2.       使用 svn copy ,

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

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

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

 

摘录合并

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

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

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

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

 

完整的合并语法

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

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

1.       Mergerevision 的起始版本

2.       Mergerevision 的最终版本

3.       MergeTARGET

简单的说,就是使用 –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:200 http://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

leftright 表示的是合并的方向, left 应该指的是源, rightTARGETold 文件

 

合并历史查看

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)

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

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

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

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

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

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

 

 

使用分支

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

Branch 分支上工作

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

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

 

关于 TAG

SVNtagbranch 并没有区别定义,他们之间的区分是人为的概念。 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

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值