进阶 - 重新设定帐号密码

  • 作者:KK

  • 发表日期:2015.12.27


这一般是大功能开发和大修改或者实施周期长的时候才用上的方案,不然别盲目使用

通过tags初步认识分支

先简单地理解一下分支,我们项目时间长了后,你可能会想到备份问题,比如说最近项目运作很稳定,你想备份所有代码和数据库,以便以后变化太多后可以重新在本地部署这个版本参考一些功能和确认状态

我们在创建SVN的时候开始是空的代码仓库,检出到客户端,这时候先建立trunk,tags,branches三个目录再在trunk目录下并提交,假设我们的SVN仓库地址是 svn://192.168.1.100/project,则我们把svn://192.168.1.100/project/trunk这个目录分发给同事们检出,那么他们的项目根目录应该是基于trunk的,他们是看不到tags和branches目录的,然后项目的一切文件都放在trunk这里进行开发,提交和更新

到了你要备份的时候,则对trunk仓库的根目录使用TortoiseSVN - 分支/标记,在"至路径"中填写/tags/bak1,"日志信息"中填写"阶段1的打包备份",然后点确定,这时候仓库就会将/trunk下的所有文件复制一份到/tags/bak1目录下,然后你的trunk可以继续进行开发,到了再想备份时再分支一个到/tags/bak2就好了(其实这里的bak1,bak2这些看你具体的区分方式了,一般按版本号命名最好,v1.0 v3.7这些),那么未来想取出这些备份的内容时自然就是检出svn://192.168.1.100/project/tags/bak2这样的地址来取得仓库内容了

你会问"为嘛要这么麻烦呢,我直接将全部文件创建一个压缩包扔进去提交不还是一样?"那样确实可以,但是可追溯性不是那么强,就是个土方法而已.而用这种分支方案,你试下在提交几个版本后再分支一次,一共至少分支两次到tags中,然后对trunk根目录用TortoiseSVN - 版本分支图,你就能看到trunk的发展历史,到了版本N被备份到tags/bak1,再到版本NN又被分支到tags/bak2等,于是你要了解bak1包含什么内容,大概是哪个阶段的话,看版本N的日志列表即可(这个要做好日志填写规范的监督咯),但其实分支的时候你都有写日志信息,这个日志信息就是用于描述本次分支的内容是个怎样的形态的,大概描述一下

这里只是说用分支实现备份功能,至少你有点明白什么叫分支了


开发分支

  • 分支的起因

    有没有过这样的经历:你接手了一个任务1,评估它要30天左右才能完成,一共要修改20多个文件(文件A,B,C,D...这些)并做好多调试工作,反正就是个麻烦事,不是几天搞得完,不是几个文件改一下就行的

    在你一天一天地修改这些文件的时候,某天用户反馈了一个BUG,上司下达一个修复工作叫任务2

    要修正它的话正好要修改文件C才可以修复,但是你的任务1也需要修改文件C,并且你已经在文件C里面改了10几行代码,并且未调试完成,还有对其它类库改动的依赖,如果你就在这个文件C中修复BUG相关的行并上线的话,则一般都会出问题,因为文件C的任务1部分代码还未完成,跑起来多少会有些问题.你就很烦啦:"我这个功能还没改完,又来一个需求还是要改同一个文件,这不是很难为吗?"

这只是一种简单的原因,还有其它情况也是会有类似问题,好了接下来实操一下开发分支就能理解情况了,在接手任务1时,你先将trunk分支一份到branches/task1,其实它和分支到task的效果是一样的,只是文件夹名称不一样,SVN不会因为这些文件夹名称不一样而有不同处理,只是我们起名字的普遍习惯

然后再本地开发机的另一处开发个新目录检出svn://192.168.1.100/project/branckes/task1,这里按之前tags的理解就是检出了一个备份,但别管它,我们基于这个目录建立项目并进行任务1的开发,注意:这里只写任务1的代码,别的一概不写!(如果是Web项目,分支后你一般还需要建立新的主机指向这个目录实现开发调试,除非你可以放弃trunk那边的主机)

然后用户反馈问题的时候来那个任务2嘛,你就在trunk下开发修复并提交(偷偷地告诉你其实我们一般将trunk称为主线),这样就不会发生修改冲突的问题啦

但是任务2是一个BUG,trunk修复了,但意味着之前分支出去的task1代码都会有相同问题是吗?如果不是很严重那还可以容忍,但是如果严重,必须在task1这个分支也修复一下,如果你已经跟着我的内容去反复尝试了几次分支,且看我下面这个分支示意图,这是当一个开发目录在版本迭代过程中发生多次分支后,对这个目录选择TortoiseSVN - 版本分支图显示出来的分支历史图,到了版本22被备份到branches/task1,再到版本30又被分支到branches/task2,并且分支中也有它自己的版本发展(代码提交)

开发分支的实际应用:除了以上是你自己的长期任务外,其实团队也是这样,只要是长期的一般都会分支出去慢慢搞,分支了就会得到一个分支的检出地址,这个地址发给相关的开发人员一齐检出一齐开发提交就可以,然后修改的代码在下面的章节就教你与主线进行合并


合并分支

好了到某一天你的任务1执行完毕了,但由于平时被发布/上线的代码总是trunk,所以task1分支的代码也要放回trunk里才可以上线.如果你想着不放,那你就要倒着把trunk最近修复的BUG放回task1分支里咯.

好了我现在要教你把task1分支的代码导入到trunk里,但接下来一般会发生很多冲突(在你准备学习这个时请记得在trunk和task1中都修改一些东西以便接下来测试,最好也修改几个相同的文件和相同的地方)

在这个情况下你先要听我说一句话:要把task1的代码导入到trunk里,那么操作就是在trunk里进行操作,倒着想"把task1"的代码吸过来

  • 操作流程:

    我们去trunk目录下空的地方选择TortoiseSVN - 合并

    要求选择合并类型,默认是"合并一个版本范围",不用修改,下一步

    "合并的源"填写svn://192.168.1.100/project/branckes/task1,"将要合并的修改版本范围"区域中选择"所有版本",下一步

    "合并深度"默认"工作副本",不用改,下面几个选项最好选择"忽略所有空白字符",不然的话在实操中可能会冲突死你,现在试验你可以随便不钩

    点"测试合并"可以看一看情况,这个我不讲解,你大概摸索下这里,接下来是点"合并"开始正式合并

    此时SVN会将branches/task1的分支代码复制过来覆盖到trunk里面,然后由于task1分支的功能修改与trunk的BUG修正/小功能添加发生共同修改的位置,于是会产生冲突(你如果想这种情况下能不能没有冲突?那是不可能的啦,trunk说要在这里修功能,branches说要在这里加功能,那电脑怎么会智能到知道你想听谁的呀?这句是老话了~~~),于是你就要开始对一个个冲突文件进行冲突的解决了,这里在大型团队中,分支一般是会有几个人在开发,主干也会有几个人在维护,当两个目录合并时,发生的冲突往往不是两个人面对面聊聊解决,而是两个团队面对面

    解决冲突后,其它没有冲突的代码也顺利合并到trunk了,此时trunk则拥有了task1的代码,但最好还是测试测试,这里对测试要求更高,因为你们的测试广度增加了,不是平时那样一个小功能测一小块,当然完备的项目管理中如果已经准备好了单元测试和验收测试,做好文档化的话,我相信这个并不是什么大问题,只是实际中并不是很多团队能做到


分分合合的感想

你是不是感到很心累?

看似分支挺规范地实现了项目管理,却又带来了部署虚拟主机/IDE创建分支项目/构建器配置/持续集成配置等问题,而且合并时还要解决冲突喔

是呀,其实我也感到疲累,不到迫不得已我们都不应该使用分支为项目管理带来更多麻烦.除非公司准备好了一套高度自动化的分支管理方案(一些开发实力强的公司可以做到,或者我们自己有心机的话,毕竟SVN都提供了编程接口)

另外,当出现3个branches分支以及4个tags备份时,如果主线发现了一个大漏洞要赶紧修复,那你想想是不是所有branches和tags都要修复才行?不然如果某天说要部署v2.0版本的tags出去,但这个版本却已经有了未来发现的大漏洞没修复可不好呀,所以尽管是以前备份的tags版本,但trunk在未来如果发现了大漏洞或必须修正的bug时,你还是很多功夫去修正的,不过其实修正tags也是必须的啦,但修branches又是多功夫了,很多人想着还是只修trunk好了.其实tags一般不修也没多大关系,因为工作中很少说要去部署过去的tags版本,我们一般只是为了备份,必要时查看过去的代码