程序员DevOps

一、版本管理-SVN单需求代码合并

2018-07-05  本文已影响66人  起点_1989

        最近在做DevOps方向的产品,已经完成了SVN和GitLab的相关功能研发。关于版本管理研发过程中使用到的技术,将会陆续更新。本篇文章主要介绍svn的代码合并功能。

        先扫盲一下,代码合并,是把一条分支上的改动(源分支),应用到另一条分支上(目标分支)。可以只合并一部分,也可以全部合并。但前提是这两条分支是有关系的分支,父子、爷孙啥的都行。那分支之间的关系是咋产生的呢?后续我会专门写一篇文章介绍,此处不做过多赘述。

        先说技术选型,作为一个java程序员,再做这一块之前,首先想到了SVNKit。SVNKit是一个纯java写的SVN客户端库,提供了很全的SVN功能接口,虽然不是开源的,但是使用是免费的。像什么checkout、update、merge、revert等等等等,应有尽有。然而!不用不知道,一用吓一跳。我当时选用的SVNKit版本是1.8.6,在数据量小,合并场景比较简单的时候,SVNKit很好用。但是当合并的版本号到达一定的数量级之后,你就等着吧,等到你想砸电脑。时不时的还出点小bug来捣捣乱。所以果断放弃SVNKit,直接自己组装SVN客户端命令。目前为止,用的还是很开心的。

      代码合并一般分两种情况。一种是按照需求号(或任务号,以下统称为需求号)进行合并,俗称cherry pick(摘樱桃)模式,另一种是整分支的合并。其中整分支的合并比较简单,直接把整条分支往其他分支上合就可以了,有冲突revert,没冲突commit。而按照需求号合并就相对复杂了很多,但无论多复杂,归根结底还是要根据版本号去做合并。

        先说一下单个需求的合并,首先研发往源分支提交代码的时候就要形成一个规范,commit log里要写需求号!!因为在做自动化合并的时候,是要根据commit log里的需求号,去找对应的版本号的。要不然我怎么知道你要合哪些版本啊?巧妇也要有米嘛对不对?根据需求号找到了版本号之后干啥呢?直接拼装merge命令往目标分支上合?不!要考虑到性能和准确度!合并代码可不是儿戏,代码可是一个公司的根基之所在啊。所以为了快而准的合并到目标分支上,我们要做一系列的前置准备工作。

        首先要剔除掉已经合并过的版本号!为了效率也为了合并时确保没毛病,这一步还是有必要做的。你自己平时用svn客户端工具合并的时候不也发现了嘛?合并过的版本号是置灰的,没办法继续合并的。假如A需求对应1000个版本号,其中有999个版本号已经合并过了,你如果不给它剔除了,那merge的时候,就得merge这1000个版本号,那肯定不如merge1个版本号快啊。

        但是!每次代码合并之前,都要剔除掉merge过的版本号呢?不!那什么时候不剔除呢?别忘了,有合就有撤,能合上去就能撤下来,能撤下来,还能合上去。这是一个闭环,懂了吧?撤下来的版本号,如果还想合,但是merge历史记录里又记录了这个版本号已经merge过了,按常理来说,就应该给剔除掉了,但是我们又通过某种方法发现它被撤下来过,那再合就不剔除它了。这一点后续会专门写一篇关于代码回滚的文章讲述。

        当合并过的版本号被剔除掉之后,我们就该对剩余这些待合并的版本号排个序了。为啥要排序呢?下面是两条简单的merge命令,看过后就明白了:

svn merge -r 0:9 -r 12:15/home/srcWorkCopy /home/destWorkCopy --username admin --password admin --non-interactive --no-auth-cache

svn merge -r 0:2 -r 2:9 -r 12:15 /home/srcWorkCopy /home/destWorkCopy --username admin --password admin --non-interactive --no-auth-cache

这就一目了然了,排序是为了组装成一个一个的连续区间,也为了把版本号从低到高依次合并。这样的话合并效率会高出很多。

        下一步是不是就可以开始合并啦?不!如果前面有个独木桥让你走,你可以选择要两次机会,还是要一次机会。如果选只要一次机会,那你掉下去就会被摔死。如果选择要两次机会,那么第一次走的时候要是掉下去,不会被摔死,第二次掉下去才会被摔死。那你是选择要一次机会还是要两次机会呢?当然要两次机会啦!一样的道理,在合并之前,我们有两次机会,第一次是预合并。第二次才是真正的合并。先做个预合并,试一下,看看结果准不准,也看看有没有冲突。如果有冲突的话,直接就不往下进行了。要是没有冲突,再进行真正的合并。说了这么多,其实就是给merge命令加个参数:

--dry-run

        那合并完了要干啥?合并完了我们就该去解析合并结果啦。说起这一点,就比SVNKit麻烦了,要是用SVNKit,直接就返回一个json格式的合并结果了。但是用命令我们还得悲催的自己去解析。没冲突还好,有了冲突还得解析是树冲突还是文件冲突还是属性冲突...这还不是最苦逼的,最苦逼的是如何把需求号、版本号、文件一一对应上。单个需求的还好,多个需求有交叉文件的情况下...哎!谁试谁知道。总之实现方式就是根据版本号和改动的文件去commit log反查对应的需求号

        上面提到了合并结果中有冲突了,一般情况下,如果使用dryrun做一下预合并是无冲突的,再真正合并的时候99%是无冲突的。但是也不排除这1%的情况。至于为什么,在后面讲多需求合并的时候会重点解释。那如果有了冲突咋办?肯定是回滚喽。此处的回滚跟我在上面提到的目标分支的代码回滚还不是一回事。这里是目标分支的本地库回滚,用到的命令如下:

svn -R revert /home/destWorkCopy

        如果合并结果没有冲突的话,那就直接提交代码到目标远程分支上就好了,注意commit log中要带需求号!因为有可能你的目标分支,也会作为源分支往另一条分支上合并的。命令如下:

svn commit -m "A-1 测试代码合并" /home/destWorkCopy

        至此,一次完整的代码合并就完成了,后面就可以进行编译打包和部署了。

上一篇下一篇

猜你喜欢

热点阅读