《SVN宇宙版教程》:第四章 TortoiseSVN核心技能之分支与合并-1

第四章 TortoiseSVN核心技能之分支与合并

导言:

分支与合并是版本控制中的重中之重,这不仅可以大大增加开发效率,而且还可以对代码进行有效的管理,SVN的GUI工具TortoiseSVN也支持在菜单中进行分支与合并的操作,使用起来相当的方便,在本章中着重用大量的篇幅去介绍这2种技术,学习完本章后会对SVN的理解更加深入。

4.1 分支Branch/tag操作

分支在软件开发过程中起到非常重要的作用,它可以将一个软件划分成不同的版本,这些版本之间具有独立性,比如在基于原有平台版本的基础上开发出普通版,专业版及旗舰版的软件产品,这样可以使开发出来的软件种类更加丰富,有利于后期代码的维护与管理。

4.1.1 为什么要使用分支

在使用SVN的时候我们往往有这样的需求,需要修改某些项目中的程序代码,但因为对修改的结果并没有十足的把握,比如有可能出现BUG这样的情况,担心自己当前的修改如果Commit提交到服务器中的版本库时会对版本库中的代码进行破坏,传统的做法是手动复制一份代码,然后修改,如果修改成功则提交到服务器,否则直接删除,这样做一定程度上虽然满足了要求,但问题是在你进行测试修改的时候如果版本仓库中的内容可能已经更新了n个版本,那么当你实验完成后再提交到版本库中的时候可能会有非常多的冲突,而且在你实验的过程中可能也会有很多的中间结果需要保存,如果没有提交,一旦开发用的电脑出现任何问题都有可能会造成之前的努力前功尽弃,所以SVN中的功能解决了这样的问题,它就是分支。分支不单解决这个问题,还满足了代码访问权限的控制,以及开发小组的再划分。在svn中,我们要做一些测试性的开发只需要在主线工程中创建一个分支即可。

使用分支还可以基于原有的项目进行临时性的功能试验,而且负责不同模块的程序员之间还可以以并发的方式进行工作,提高软件设计的效率。

下面来介绍一下SVN仓库中默认的3个文件夹的作用,如图4.1所示。

图4.1 仓库中默认存在3个文件夹

 

英语单词trunk的翻译如图4.2所示。

图4.2 单词trunk的英译汉翻译

 

所以文件夹trunk主要存放的就是进展中的项目,是项目的主流程。

单词branch的翻译如图4.3所示。

图4.3 单词branch的英译汉翻译

 

文件夹branch存在的意义在于在不干扰trunk的情况下,和trunk并行开发,待开发结束后再合并回trunk中,在branch和trunk各自开发的过程中,它们都可以不断地提交自己的修改,而每次修改都在仓库中被记录。

文件夹branch的主要作用就是存放项目主流程的分支。比如在开发医院管理系统时可以有一个基础的业务平台,业务平台中有最基本的医院管理系统的模块,例如挂号模块,医生工作站模块,药房及药库等工作站模块,但每一个医院的业务有可能出现细微上的不同,那么这家软件公司就要基于这个基础的业务平台来开发出针对A医院业务的A系统,针对B医院业务的B系统,还有针对C医院业务的C系统等,这时就是使用分支的好时机。其实什么时机去创建分支,什么时机将代码存放在branch文件夹中,也就是创建分支的时机完全由人的主观意识再结合业务规范和需求来决定的,这绝对不是强制性的,就像log日志中的等级一样,总有些人认为这个错误是轻微的,而有些人认为这个错误是严重的一样。

还有另外一种情况可以使用branch分支,比如有多个人同时开发时,A程序员有一个想法跟原先的设计不太一致,所以想要改动代码来做一个尝试,但这个改动代码的行为可能需要花一段时间来完成,但在这个过程中,A程序员的一些操作可能会影响B程序员的工作,A程序员从现有的项目中再单独创建出另一个测试用的Project的话又不能及时得到 B程序员对已有代码做的修正,而且单独创建测试用的Project时A程序员如果实验成功后还要跟原来的代码进行合并也存在一些困难,这时最好的实践方法还是使用branche分支,A程序员只需要在trunk主流程中建立一个自己的branch,然后在里面进行实验,必要的时候从B程序员的trunk中取得更新,或者将自己的阶段成果汇集到trunk中,这种情况也是使用分支的好时机。

    单词tag的翻译如图4.4所示。

图4.4 单词tag的英译汉翻译

 

既然tag翻译成标签,那么标签就可以对一件事物进行定性,所以tag文件夹主要存放的就是一些milestone里程碑式的项目,不管这个项目是不是最终版,只要有突破性的进展即可以将代码存放在tag文件夹中,那么大多数的情况下tags文件夹中的源代码是只读的,不允许更改的!

举一个示例,比如软件项目1.0开发完成,所以为了纪念这个划时代的进度,就要对1.0版本的软件项目做一个tag标签,定义为tag_release_1_0,然后再基于这个tag_release_1_0项目做1个release版本。项目是一直进展的,所以trunk进入了1.1的开发,但是在客户使用trunk的1.0版本中发现了bug,那么就需要基于tag_release_1_0做一个branch,branch_bugfix_1_0,基于这个分支进行bug的修改,等到bug修改结束,再做一个tag,名称为tag_release_1_0_1,然后根据需要决定branch_bugfix_1_0是否并入trunk版本中。

不过建议对tag文件夹设置为只读属性。而branch文件夹是用来做并行开发的,这里的并行是指和trunk文件夹中的项目进行比较,这样大家就知道trunk是主线工程,而branch文件夹中是分支工程,而tag文件夹中的内容是里程碑式的软件项目了。

4.1.2 创建分支Branch

Step01:创建新的仓库a,还要在桌面创建aData数据源文件夹,内容如图4.5所示。

图4.5 文件夹aData中的内容

 

    Step02:使用file:///协议将aData中的内容导入到a仓库中的trunk文件夹中,界面如图4.6所示。

图4.6 将aData导入到trunk主线文件夹中

 

    Step03:成功Import后的效果如图4.7所示。

图4.7 成功导入revision的值是2

 

Step04:将仓库a/trunk中的全部内容以选项Fully recursive进行Checkout导出到桌面aCheckout文件夹中,配置界面如图4.8所示。

图4.8 将路径file:///C:/svn_repository/a/trunk进行导出

 

Step05:对aCheckout文件夹中的文件进行更改内容如图4.9所示。

图4.9 更改a.txt和z.txt文件内容

 

    Step06:对aCheckout文件夹执行Commit菜单效果如图4.10所示。

图4.10 第1次成功更改

 

    Step07:继续对aCheckout文件夹中的文件进行更改内容如图4.11所示。

图4.11 第2次更改txt文件

 

    Step08:执行Commit菜单后的效果如图4.12所示。

图4.12 第2次成功更改

 

这时仓库a和桌面aCheckout文件夹中的内容是一致的,是同步的,下一步就要创建一个分支。

Step09:对aCheckout文件夹调用菜单如图4.13所示。

图4.13 单击Branch/tag菜单

 

    Step10:弹出界面如图4.14所示。

图4.14 创建分支界面的默认配置

 

    Step11:在此界面中可以单击右上角的按钮来选择目标分支的路径,如图4.15所示。

图4.15 选择/branches/aHIS路径

 

    Step12:在分支路径/branches后面追加路径/aHIS代表此分支是属于a医院的。

    Step13:配置完成后的界面如图4.16所示。

图4.16 最终准备要单击OK按钮的界面

 

    “Create copy in the repository from”选择“HEAD revision in the repository”的含义是直接在工作副本所关联的仓库中将最新版的内容生成一个分支,也就是在服务器端直接生成分支。选项“Specific revision in repository”含义是使用仓库中指定revision版本创建分支,而选项“Working copy”是使用工作副本当前的状态去创建分支,在这里需要留意的是,当前的状态不是指工作副本当前Revision版本的内容,当前的状态是有可能工作副本的内容被修改了,但并未提交,但还是用修改后的这个内容来创建分支,这3种选项在后面的步骤中都会给大家进行介绍。

    另外在这里需要说明的是,在TortoiseSVN软件中创建分支的目标路径aHIS必须是硬盘上不存在的路径。

    注意:在此界面中有1个项目引用externals列表及“Switch working copy to new branch/tag”选项,在后面的章节将会对这2个选项进行实验,在这里保持默认即可。

Step14:继续操作,单击OK按钮后成功创建了分支,效果如图4.17所示。

图4.17 成功创建branch分支

 

    Step15:在branches文件夹中成功创建了分支,如图4.18所示。

图4.18 成功创建aHIS分支文件夹Revision是5

 

    Step16:在aHIS分支中也有内容,如图4.19所示。

图4.19 分支aHIS中的内容版本是4因为并未修改

 

Step17:如果继续对桌面中aCheckout文件夹执行Branch/tag菜单后配置选项界面如图4.20所示。

图4.20 将指定revision版本的内容生成branches分支

 

    “Create copy in the repository from”选择“Specific revision in repository”的含义是直接在工作副本所关联的仓库中将指定Revision版本的内容生成一个分支,也是在服务器端直接生成分支。

    Step18:单击OK后成功在a仓库中创建分支,里面的txt文件内容就是revision版本为2的内容,如图4.21所示。

图4.21 txt的内容都是revision版本为2的内容

 

    Step19:继续操作,将桌面aCheckout文件夹中的a文件夹用TortoiseSVN的Delete菜单删除,效果如图4.22所示。

图4.22 用Delete菜单删除a文件夹

 

    Step20:然后再编辑a.txt文件内容如图4.23所示。

图4.23 编辑a.txt为新内容

 

    Step21:再添加b.txt文件,并向b.txt添加文本内容及设置b.txt文件为Add状态,效果如图4.24所示。

图4.24 处理b.txt文件

 

Step22:下一步千万不要对aCheckout文件夹调用Commit提交菜单,那样做会破坏实验的环境。

Step23:继续操作,调用Branch/tag菜单后配置选项界面如图4.25所示。

图4.25 使用Working copy中的内容生成branches分支

 

    Step24:单击OK按钮后cHIS中的内容如图4.26所示。

图4.26 使用工作副本的当前状态来创建分支

 

4.1.3 选项Set explicit revision for these externals的使用

    举一个例子来说明Set explicit revision for these externals选项的使用,比如有a和b仓库,a仓库引用b仓库,这时如果对a仓库创建出一个分支,并且设置Set explicit revision for these externals选项呈复选的状态,则说明创建出来的分支永远使用当时指定revision版本的b仓库,即使b仓库代码更改而分支中的代码还是旧revision版本的代码。如果不复选,则分支使用b仓库的代码永远都是最新版本。

Step01:此实验继续使用模板仓库a,但对仓库a中的文件夹结构进行处理如图4.27所示

图4.27 重构模板仓库a的文件夹结构

 

Step02:对模板仓库a文件夹复制粘贴成仓库b,也就是说它们俩的结构及内容是一模一样,如图4.28所示。

图4.28 仓库a和b一模一样

 

Step03:在仓库a中的trunk文件夹配置引用仓库b,引用的关键配置如图4.29所示。

图4.29 仓库a/trunk路径中引用b的关键配置

 

Step04:配置成功的内容如图4.30所示 :

图4.30 仓库a成功引用仓库b

 

    Step05:将路径file:///C:/svn_repository/a/trunk中的内容导出到桌面x文件夹中,再对x文件夹调用Branch/tag菜单后配置选项界面如图4.31所示。

图4.31 对x文件夹生成分支

 

    Step06:选项“Set explicit revision for these externals”中的内容并未复选,说明仓库b中的内容更新时,分支x中的代码也同步更新,单击OK后分支成功创建,效果如图4.32所示。

图4.32 分支xHIS成功创建

 

    Step07:这时将仓库b/trunk导出到桌面bCheckout并且添加“newadd.txt”文件,内容如图4.33所示。

图4.33 添加1个txt文件及内容

 

    Step08:对bCheckout文件夹执行Commit菜单后的效果如图4.34所示。

图4.34 成功更新仓库b中的内容

 

    Step09:这时再到分支xHIS中可以看到引用最新版的b仓库了,如图4.35所示。

图4.35 分支成功引用其它项目的最新版

 

    Step10:再继续实验,将路径file:///C:/svn_repository/a/trunk导出到桌面z文件夹,对文件夹z调用Branch/tag菜单后配置选项界面如图4.36所示。

图4.36 对z文件夹生成分支

 

Step11:选项“Set explicit revision for these externals”中的内容已复选,说明仓库b中的内容更新时,分支z中的代码一直使用的是revision版本为6的代码,不使用仓库b最新版的代码,而仓库b的revision版本是6的txt内容如图4.37所示。

图4.37 仓库b的revision版本为6的内容

 

Step12:单击OK后分支zHIS成功创建如图4.38所示。

图4.38 分支zHIS成功创建

 

    Step13:这时对桌面bCheckout中的内容继续更改如图4.39所示。

图4.39 继续更改newadd.txt文件的文本

 

    Step14:对bCheckout文件夹执行Commit提交按钮,则revision值变成7,如图4.40所示。

图4.40 仓库b再一次被更新

 

    Step15:而分支zHIS中的内容依然还是revision值为6的版本,如图4.41所示。

图4.41 分支zHIS一直引用的是旧的版本

 

4.1.4 选项Switch working copy to new branch/tag的使用

    如果对选项Switch working copy to new branch/tag进行复选则创建完分支后工作副本自动切换到分支的路径中,将路径file:///C:/svn_repository/a/trunk导出Checkout到桌面aa文件夹中,这时aa文件夹的属性如图4.42所示。

图4.42 文件夹aa引用的仓库路径为a/trunk

 

    Step01:对aa文件夹调用Branch/tag菜单后配置选项界面如图4.43所示。

图4.43 对aa文件夹创建分支

 

    Step02:对“Switch working copy to new branch/tag”选项进行复选,单击OK按钮后不仅分支aaHIS成功创建,桌面文件夹aa中的内容指向的是分支的路径,如图4.44所示。

图4.44 工作副本中的内容自动切换到分支的路径了

4.1.5 主线更改后不影响分支的实验

    Step01:初始化实验环境删除C:\svn_repository中的所有仓库,使用全新的模板仓库a,不需要更改仓库a的文件夹结构,将仓库路径file:///C:/svn_repository/a/中的内容全部导出到桌面atest文件夹后再对atest创建分支,配置分支的代码如图4.45。

图4.45 创建分支的配置界面

 

    Step02:单击OK按钮后成功创建分支如图4.46所示。

图4.46 成功创建分支

 

    Step03:对atest文件夹中的a.txt进行更改如图4.47所示。

图4.47 更改根文件夹中的a.txt文件

 

    Step04:这时对atest文件夹执行Commit菜单命令向仓库a中进行更新数据,成功更新的效果如图4.48所示。

图4.48 成功更新revision值是6

 

    Step05:打开file:///C:/svn_repository/a/branches/atestA/a.txt文件后的效果如图4.49所示。

图4.49 分支中的a.txt内容还是旧版

 

通过此实验可以得知,分支的操作是以复制Copy的方式进行创建,在默认的操作下主线中的代码被更改并不影响分支中的代码。

4.1.6 主线与分支拥有自己的revision版本号实验

Step01:初始化实验环境删除C:\svn_repository中的所有仓库,使用全新的模板仓库a,将仓库a导出到桌面atest文件夹如图4.50所示。

图4.50 将仓库a导出到atest文件夹

 

Step02:再对atest创建分支,配置分支的代码如图4.51所示。

图4.51 创建分支的配置界面

 

    Step03:单击OK按钮成功创建了分支如图4.52所示。

图4.52 分支的revision版本号+1了

 

    Step04:查看路径file:///C:/svn_repository/a/branches中的atestA分支的版本号也的确是5,如图4.53所示。

图4.53 分支仓库中的revision版本号也是5

 

    Step05:对桌面atest文件夹中的文件进行更改并Commit提交到file:///C:/svn_repository/a/仓库路径中,成功提交的界面如图4.54所示。

图4.54 仓库a的revision值是6

 

    Step06:再继续对桌面atest文件夹中的文件进行更改并Commit提交到file:///C:/svn_repository/a/仓库路径中,成功提交的界面如图4.55所示。

图4.55 仓库a的revision值是7

 

    Step07:继续操作,将路径file:///C:/svn_repository/a/branches/atestA导出到桌面atestA文件夹中,如图4.56所示。

图4.56 分支仓库中revision的值也是7

 

    Step08:说明分支与主线在逻辑上虽然“脱离”了关系,但物理上还是具有关联的效果,那么根据revision值是7的结果,所以更改桌面atestA分支文件夹中的内容后,分支仓库被更新后的revision值是+1等于8,将桌面atestA文件夹执行Commit菜单提交到file:///C:/svn_repository/a/branches/atestA路径后的效果如图4.57所示。

图4.57 分支仓库revision的值是8

 

    Step09:继续操作,更改桌面atest中的内容后执行Commit菜单将最新版的内容提交到路径file:///C:/svn_repository/a/中的效果如图4.58所示。

图4.58 更新atest后的revision值是9

 

通过此实验可以得知主线和分支的revision版本号都是在彼此revision版本号的基础上进行持续加1的效果。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值