基于Maven和SVN的项目版本管理

流程demo.png

概述/背景

项目在开发过程中的版本,和在发布时的版本应该有所区别。发布的版本应该保证一个版本号对应唯一的内容。

之前遇到过一个项目,因为pom中的版本号没有-SNAPSHOT,导致两个环境依赖的项目虽然版本号相同,其实不是同一个。当时得出结论:相同的版本号只应该对应一个内容。

后来系统学习了下Maven,才具体了解到Maven体系中关于项目版本的标准,这里分享出来,希望大家在维护项目版本的时候有据可依。

另外,Maven中的版本管理需要结合软件版本控制工具使用,如Git、SVN等。虽然目前Git的使用已经很普遍了,我的工作环境使用的是SVN,就以SVN为例进行介绍。

Maven范围的版本和SVN范围的版本有不同的含义。前者面向的是项目,代码多次修改,项目的版本号可以不变;后者面向的是代码,每一次修改都是一个不同的版本。下文所说的版本一般是指项目的版本,特殊情况下会说明是代码版本。

快照版本和发布版本

快照版本对应开发过程中的版本,特点是快速的迭代更新,同样的版本号对应的是项目在一段时间内的开发过程。

发布版本应该是一个稳定的版本,它应该对应项目在某个时刻的状态 —— 它对应唯一的代码版本。

快照版本和发布版本.png

快照版本使用-SNAPSHOT后缀。

在Maven体系中的区别

Maven解析依赖的一般机制是:先从本地仓库找,找不到再从远程仓库找。换言之,在本地仓库找到了,就不会再去找远程仓库。

如果有2个项目并行开发,其中一个项目B依赖于另一个项目A。想象一下A和B都是持续更新的,项目B的开发人员如何确保能实时获取项目A的最新内容?

方案一:项目B的开发人员,每次构建之前都手动从本地仓库删除项目A,这样构建的时候就会从远程仓库下载最新的A。

方案二:项目B的开发人员,迁出项目A的代码,自己将A项目安装到本地仓库。

这两个个方案都不是Maven体系推荐的做法,方案二让项目B的开发人员不得不去搭建项目A的开发环境,而且项目A如果出现代码问题,项目B的开发人员可能就无能为力了。方案一增加了需要人工介入的工作量。

Maven使用SNAPSHOT来解决这个问题。如果项目依赖的是一个SNAPSHOT版本的依赖,Maven会定期从远程仓库获取最新的内容,默认频率是一天一次。也可以使用-U参数来强制更新。

所以,项目A使用SNAPSHOT版本,项目B就可以定期或者实时获取项目A的最新内容。

反之,如果项目A没有使用SNAPSHOT,项目B在第一次从远程仓库下载项目A到本地仓库之后,就一直使用本地仓库的这个备份。即使项目A更新了,项目B也不会知道,除非人工删除了项目A在本地仓库的副本。

所以,开发过程中的版本,应该使用SNAPSHOT版本。

发布版本的版本号约定

一般的情况下是下面这种结构:

<主版本>.<次版本>.<增量版本> 比如 1.1.2

各版本的作用如下:

  • 主版本
    项目的重大架构变更
  • 次版本
    较大范围的功能变化
  • 增量版本
    大量或紧急bug修复

这只是一个粗略的划分,大家可以根据自己的情况讨论每一个版本的使用场景。

通常主版本、次版本都会有,增量版本视情况而定。

更进一步的情况,可以添加里程碑版本,版本的结构如下:

<主版本>.<次版本>.<增量版本>—<里程碑版本>3.1.2-alpha-1

里程碑版本表示达成项目的某个里程碑,但通常不够稳定。大部分的公司应该不会使用里程碑版本,在此略过不表。

版本维护流程

主干、标签和分支

  • 主干
    无需多说
  • 标签
    标记某个有意义的代码版本,每一个发布版本都应该打一个标签。
  • 分支
    用于并行开发,通常用于已有版本的bug修复。

流程demo

流程demo.png
  1. 在主干进行1.0.0-SNAPSHOT的开发,开发完成之后提交修改的代码到主干。修改版本为1.0.0,再次提交,并添加标签。
  2. 随后将版本改为1.1.0-SNAPSHOT,提交。然后开始新一轮的开发,完成之后提交代码,修改版本为1.1.0,再次提交并打标签。
  3. 接着将版本号改为1.2.0-SNAPSHOT,提交,并开始新一轮的开发,在开发过程中1.1.0遇到一个紧急的bug,新建分支并1.1.1-SNAPSHOT,修改版本号为1.1.1-SNAPSHOT,提交并开始1.1.1-SNAPSHOT的开发。
  4. 1.1.1-SNAPSHOT开发完成,提交代码。修改版本号至1.1.1,提交并打上标签。此时可以及时把1.1.1发布出去。同步分支到主干。
  5. 随后,1.2.0-SNAPSHOT开发完成..

版本号的修改应该作为一次单独的提交。在发布的时候,项目版本号初始为SNAPSHOT版本,提交完所有的代码之后,修改版本号为发布版本,再提交;这次提交只修改版本号。
在开始新一轮的开发过程时,修改版本号为新的SNAPSHOT,然后立即提交而不是修改代码,版本号提交之后再开始开发,这次提交只修改版本号。

SVN相关操作

SVN简单介绍

SVN是一个很简单的版本控制工具,你可以下载VisualSVN Server来搭建自己的SVN服务器。

SVNServer存储结构.png

SVN的代码主要是在仓库里管理的,如上图demo就是一个仓库。完整的仓库目录结构如下:

仓库目录(Repositories)
  |-- 仓库1
       |-- 项目1
            |-- 主干(trunk)
                 |-- 项目代码
            |-- 标签目录(tags)
                 |-- 标签1
                      |-- 项目代码
            |-- 分支(branches)
                 |-- 分支1
                      |-- 项目代码

可以看到,SVN的每一个标签或者分支,都是一份完整的代码副本

与仓库同一个级别的是用户等其他,可以控制对仓库的读写权限,具体没有深入研究,大家有需要自己研究下。

SVN操作

这里介绍上文版本维护流程中涉及到的操作。这里以命令的方式介绍,使用客户端界面的自己找一下操作的位置。

初始化项目

初始化项目首先要在VisulSVN Server的具体仓库下新建一个项目结构:

仓库-> 右键 -> 新建 –> Project Structure …

之后会生成一个标准的项目结构,包含了trunk、branches、tags,没有代码。

获取trunk的url地址,通过trunk -> 右键 -> Copy URL…

在本地项目所在目录,输入以下命令:

svn import -m "initial import" . https://PC-LIJINLONG9.hikvision.com:444/svn/demo/demo-version/trunk

添加标签

版本号修改为发布版本之后,应该立即对当前状态添加一个标签:

svn copy https://PC-LIJINLONG9.hikvision.com:444/svn/demo/demo-version/trunk https://PC-LIJINLONG9.hikvision.com:444/svn/demo/demo-version/tags/1.0-RELEASE -m "tag 1.0-RELEASE"

创建分支

svn copy https://PC-LIJINLONG9.hikvision.com:444/svn/demo/demo-version/tags/1.0-RELEASE https://PC-LIJINLONG9.hikvision.com:444/svn/demo/demo-version/branches/1.0.1-SNAPSHOT -m "create branch 1.0.1-SNAPSHOT"

可以看到,添加标签和创建分支本质上都是复制。

切换分支

svn switch https://PC-LIJINLONG9.hikvision.com:444/svn/demo/demo-version/branches/1.0.1-SNAPSHOT

合并分支

svn merge https://PC-LIJINLONG9.hikvision.com:444/svn/demo/demo-version/branches/1.0.1-SNAPSHOT

合并分支的时候,pom文件中的版本号会有冲突。一般选择使用当前的版本号

Maven的release插件

在使用自动化的插件之前,建议先手动执行上面的流程,熟悉版本维护的流程之后,再去使用自动化插件。

配置pom文件

pom文件需要添加scm配置和插件配置。scm是Software configuration management的缩写。

<project>
    ...

    <scm>
        <connection>scm:svn:https://PC-LIJINLONG9.hikvision.com:444/svn/demo/demo-version/trunk</connection>
        <developerConnection>scm:svn:https://PC-LIJINLONG9.hikvision.com:444/svn/demo/demo-version/trunk</developerConnection>
        <url>https://PC-LIJINLONG9.hikvision.com:444/svn/demo/demo-version/trunk</url>
    </scm>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-release-plugin</artifactId>
                <version>2.5.3</version>
                <configuration>
                    <tagBase>https://PC-LIJINLONG9.hikvision.com:444/svn/demo/demo-version/tags</tagBase>
                    <branchBase>https://PC-LIJINLONG9.hikvision.com:444/svn/demo/demo-version/branches</branchBase>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

scm中配置了trunk的url,connection和developerConnection的值都以scm开头,之后跟着版本控制工具的类型svn。除了svn之外,Maven还支持其他的工具,如git。

插件里配置了标签的url和分支的url,其实如果项目的结构是标准的,trunk、tags和branches在同一级,可以不用配置这两项。

配置完之后,就可以通过mvn命令来自动发布、打标签、创建分支了。

自动发布

插件把发布分为2步,第1步执行上文中版本维护流程中介绍的发布流程,第2步使用mvn deploy部署构建至仓库。第1步由插件的prepare来完成,第2步由插件的perform目标来完成。

如果prepare执行失败,可以通过rollback目标来回滚,但是prepare生成的标签需要手动删除。

release:prepare

prepare负责预发布,在prepare之前,需要确保所有的修改都已经提交了,而当前的pom文件中的版本号还没有升级为发布版本号。

prepare所做的工作有:

  1. 检查系统是否有未提交的代码
  2. 询问用户发布版本号、标签和下一个开发版本号,并提供默认值。
    What is the release version for "demo-version"? (com.hikvision.demo:demo-version) 1.2: :
    What is SCM release tag or label for "demo-version"? (com.hikvision.demo:demo-version) demo-version-1.2: :
    What is the new development version for "demo-version"? (com.hikvision.demo:demo-version) 1.3-SNAPSHOT: :
    
  3. 修改pom-根据用户的输入,将快照版本升级为发布版本
  4. 修改pom-根据用户的输入,将scm中的地址改为标签对应的地址
  5. 执行Maven构建
  6. 提交pom变更
  7. 根据用户的输入,新建标签
  8. 修改pom-根据用户的输入将version升级为新的快照版本,将scm信息更新。
  9. 提交pom变更。

上述的内容,正是我们在升级项目版本需要做的事情。

使用命令:mvn release:prepare

release:rollback

回退release:prepare的所执行的操作,并提交。但是历史记录会保留,创建的标签页不会删除。

使用命令:mvn release:rollback

release:perform

执行版本发布。是基于发布版本标签地址所对应的代码进行mvn deploy的结果。

使用命令:mvn release:perform

release:branch

自动创建分支。

使用命令:

mvn release:branch -DbranchName=1.1.1 -DupdateBranchVersions=true -DupdateWorkingCopyVersions=false

参考

  1. 《Maven实战》 - 许晓斌
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容