从 git branch 派生 Maven 工件版本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13583953/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Deriving maven artifact version from git branch
提问by Thorbj?rn Ravn Andersen
We have a workflow requirement that essentially mean that we need to have the artifact version of a module externally defined from the current branch in git.
我们有一个工作流需求,这实质上意味着我们需要从 git 中的当前分支外部定义模块的工件版本。
I.e. if we are on the master branch in git, I need <version>master-...</version>
and if we are on the bugfixX branch, I need <version>bugfixX-....</version>
for the generated artifact for this pom.xml.
即如果我们在 git 的 master 分支上,我需要<version>master-...</version>
,如果我们在 bugfixX 分支上,我需要<version>bugfixX-....</version>
为这个 pom.xml 生成的工件。
I have previously found that https://github.com/koraktor/mavanagaiatacan provide the SHA-1 hash as a property and it appears from the documentation that it can also provide the branch, so perhaps if it could be run early enough in the process we could set the property and just put <version>${our.version}</version>
in the pom. If this is possible, I would very much like to see a working pom.xml (and reward a 500 point bounty for it too).
我以前发现https://github.com/koraktor/mavanagaiata可以提供 SHA-1 哈希作为属性,并且从文档中可以看出它也可以提供分支,所以也许如果它可以在足够早的时间内运行我们可以设置属性并将其放入<version>${our.version}</version>
pom.xml 的过程中。如果这是可能的,我非常希望看到一个有效的 pom.xml(并为此奖励 500 点赏金)。
If not, I guess we are into either preprocessing or "git checkout" do extra magic with some of the hooks (which I have not yet tried, working code would be great too).
如果没有,我想我们要么是预处理,要么是“git checkout”,用一些钩子做额外的魔法(我还没有尝试过,工作代码也很棒)。
We have a top level pom, which can be run to generate a property file in ".." before building the modules where this functionality I'm asking about needs to go.
我们有一个顶级 pom,可以运行它以在“..”中生成一个属性文件,然后再构建我所询问的这个功能需要去的模块。
Any suggestions on how to solve this?
有关如何解决此问题的任何建议?
回答by Timur
Indeed, Maven can't change the version of it's own project in one run with other goals. On top of it, as far as I know, Maven doesn't support arbitrary properties in the <version>
tag. Therefore, a separate execution is required to run a goal which will change the version of the POM. There are various plugins which can do it - for this case one might use the versions:set
goal from versions
plugin - http://mojo.codehaus.org/versions-maven-plugin/set-mojo.html
事实上,Maven 不能在一次运行中改变它自己项目的版本和其他目标。最重要的是,据我所知,Maven 不支持<version>
标签中的任意属性。因此,需要单独执行以运行将更改 POM 版本的目标。有各种插件可以做到这一点 - 对于这种情况,可以使用插件中的versions:set
目标versions
- http://mojo.codehaus.org/versions-maven-plugin/set-mojo.html
So, one might execute it as follows for example:
因此,可以按如下方式执行它,例如:
mvn versions:set -DgenerateBackupPoms=false -DnewVersion=$branch-SNAPSHOT
where the $branch
variable has to contain current Git branch name; it can be extracted with git rev-parse
, like this:
其中$branch
变量必须包含当前的 Git 分支名称;它可以用 提取git rev-parse
,像这样:
branch=$(git rev-parse --abbrev-ref HEAD)
But still, one needs to execute it somehow. You can do manually, but it is cumbersome. So, my guess is that indeed the most robust solution would be to approach this from Git side. That is - a Git hook. Here is the complete Git post-checkout
hook which will do the job (same code as above with some filtering to run the hook only when the branch is checked out, not the individual files only):
但是,仍然需要以某种方式执行它。手动也可以,但是比较麻烦。所以,我的猜测是,确实最强大的解决方案是从 Git 方面解决这个问题。那就是 - 一个 Git 钩子。这是完成post-checkout
这项工作的完整 Git钩子(与上面相同的代码,带有一些过滤器,仅在签出分支时运行钩子,而不是仅在单个文件中运行):
#!/bin/bash
echo 'Will change the version in pom.xml files...'
# check if the checkout was to checkout a branch
if [ != '1' ]
then echo 'git checkout did not checkout a branch - quitting';exit
fi
# get current branch name
branch=$(git rev-parse --abbrev-ref HEAD)
version=$branch-SNAPSHOT
# run maven versions plugin to set new version
mvn versions:set -DgenerateBackupPoms=false -DnewVersion=$version
echo 'Changed version in pom.xml files to $version'
Put this content to the file PROJECTDIR\.git\hooks\post-checkout
file. Note that the hook file should be executable to run it (chmod +x post-checkout
).
将此内容放入文件PROJECTDIR\.git\hooks\post-checkout
file。请注意,挂钩文件应该是可执行的才能运行它 ( chmod +x post-checkout
)。
Few notes about versions
plugin - it is pretty flexible and supports many options and have few other goals which might be of help, depending on your project structure (do you use parent poms or not, do childs have their own versions or do they derive from parent, etc.). So, the hook above might be modified slightly to support you specific case by using other goals from versions
plugin or by specifying additional parameters.
关于versions
插件的一些注意事项- 它非常灵活,支持许多选项,并且几乎没有其他目标可能会有所帮助,具体取决于您的项目结构(您是否使用父 poms,孩子是否有自己的版本或他们是否从父母派生) , 等等。)。因此,上面的钩子可能会稍作修改,以通过使用versions
插件中的其他目标或指定其他参数来支持您的特定情况。
Pros:
优点:
- Robust
- No need to change anything in the pom.xml files themselves to make this work
- This "functionality" can be turned off simply by deactivating the hook (remove or make not executable) - again, no changes are required in the pom.xml
- 强壮的
- 无需更改 pom.xml 文件本身中的任何内容即可完成此工作
- 只需通过停用挂钩(删除或使其不可执行)即可关闭此“功能” - 同样,不需要在 pom.xml 中进行任何更改
Cons:
缺点:
- One can't enforce others to use a hook - it should be installed manually after the repo is cloned (or, you can provide a script to install the hook if supposed Git users are afraid of touching the stuff inside .git directory).
- 不能强制其他人使用钩子 - 它应该在克隆 repo 后手动安装(或者,如果假定 Git 用户害怕接触 .git 目录中的内容,您可以提供一个脚本来安装钩子)。
UPDATE
更新
Hereafter is the more complicated version of the hook, which will not only set the version to the branch name, but will also preserve the suffix of the old version. For example, provided old version master-1.0-SNAPSHOT
, switching to feature1
branch will change the version of the project to feature1-1.0-SNAPSHOT
. This bash script suffers from few problems (requires branch names without dash symbol (-
) in the name, and only takes the version of the root pom), but may give an idea of how the hook may be extended: given a mix of mvn and bash commands you can extract and update quite a lot of the information in the POM.
此后是更复杂的钩子版本,不仅会将版本设置为分支名称,还会保留旧版本的后缀。例如,提供旧版本master-1.0-SNAPSHOT
,切换到feature1
分支会将项目的版本更改为feature1-1.0-SNAPSHOT
. 这个 bash 脚本遇到的问题很少(需要名称中没有破折号 ( -
) 的分支名称,并且只需要根 pom 的版本),但可能会给出如何扩展钩子的想法:混合使用 mvn 和bash 命令可以提取和更新 POM 中的大量信息。
#!/bin/bash
echo 'Will change the version in pom.xml files...'
# check if the checkout was to checkout a branch
if [ != '1' ]
then echo 'git checkout did not checkout a branch - quitting';exit
fi
# get current branch name
branch=$(git rev-parse --abbrev-ref HEAD)
# get current version of the top level pom
current_version=$(mvn help:evaluate -Dexpression=project.version | grep -v '\[.*')
# extract version suffix
suffix=$(echo $current_version | cut -d \- -f 2)
# build new version
version=$branch-$suffix
# run maven versions plugin to set new version
mvn versions:set -DgenerateBackupPoms=false -DnewVersion=$version
echo 'Changed version in pom.xml files to $version'
回答by Matthieu BROUILLARD
Sorry to revive this question and to post very lately another solution but it is possible indeed to change maven version dynamically and to use some git features, a little bit like git describe
would do.
很抱歉恢复这个问题并最近发布了另一个解决方案,但确实可以动态更改 maven 版本并使用一些 git 功能,有点像git describe
会做的。
The project that does this is jgitver-maven-plugin(disclaimer; I am the author), it uses jgitvera jgit based library in order to derive maven project version from git information .
执行此操作的项目是jgitver-maven-plugin (免责声明;我是作者),它使用jgitver一个基于 jgit 的库,以便从 git 信息中导出 maven 项目版本。
It is very easy to use as a maven extension
作为 Maven 扩展非常容易使用
...
<build>
<extensions>
<extension>
<groupId>fr.brouillard.oss</groupId>
<artifactId>jgitver-maven-plugin</artifactId>
<version>0.1.0</version>
</extension>
</extensions>
...
</build>
...
The extension can also be used as a plugin extension, and then allows more configuration , for example in case you would not like to use SNAPSHOTS. See the projectpage for a description of full usage scenarios.
该扩展还可以用作插件扩展,然后允许更多配置,例如,如果您不想使用 SNAPSHOTS。有关完整使用场景的描述,请参阅项目页面。
There is also a gradle pluginavailable that does more or less the same.
还有一个gradle 插件可用,它的作用或多或少相同。
[edit 1]: answer to Thorbj?rn Ravn Andersen comment
[编辑 1]:回答 Thorbj?rn Ravn Andersen 评论
The plugin does not modify the original pom files or the build.gradle files.
For the maven plugin, modifications are done both in memory in the maven Object Model and written to a temporary file in temp directory. The calculation is based on the git metadata only (tags, commits, ...).
This non modification allows to not pollute the git history. WHen your are satisfied with a git commit, tag it git tag -a x.y.z
and mvn deploy
: that's all.
The version in your project files, is now useless and can be set to 0 for example.
该插件不会修改原始 pom 文件或 build.gradle 文件。
对于 maven 插件,修改在 maven 对象模型的内存中完成,并写入临时目录中的临时文件。计算仅基于 git 元数据(标签、提交等)。
这种非修改允许不污染 git 历史记录。当您对 git commit 感到满意时,标记它,git tag -a x.y.z
然后mvn deploy
:就是这样。
项目文件中的版本现在已无用,例如可以设置为 0。
As of today, and due to IDEA-155733only recent EAP versions of IntelliJ work with the maven plugin. Eclipse & Netbeans have no problem.
截至今天,由于IDEA-155733,只有 IntelliJ 的最新 EAP 版本才能使用 maven 插件。Eclipse & Netbeans 没有问题。
回答by qoomon
Disclaimer: I am the author
免责声明:我是作者
My maven core extension will virtually set the version based on the current branch or tag. You can config custom version format patterns as you like.
我的 maven 核心扩展将根据当前分支或标签虚拟设置版本。您可以根据需要配置自定义版本格式模式。
https://github.com/qoomon/maven-branch-versioning-extension
回答by ?yvind Matheson Wergeland
If it is sufficient to set the git tag and version information in the artifact file name, you can use maven-jgit-buildnumber-plugin:
如果在工件文件名中设置 git 标签和版本信息就足够了,可以使用maven-jgit-buildnumber-plugin:
<build>
<finalName>${artifactId}-${git.buildnumber}</finalName>
<plugins>
<plugin>
<groupId>ru.concerteza.buildnumber</groupId>
<artifactId>maven-jgit-buildnumber-plugin</artifactId>
<version>1.2.7</version>
<executions>
<execution>
<id>git-buildnumber</id>
<goals>
<goal>extract-buildnumber</goal>
</goals>
<phase>prepare-package</phase>
</execution>
</executions>
</plugin>
<!-- more plugins -->
</plugins>
</build>
回答by Ed Randall
From maven-3.5.0on there is support for ${revision}, ${sha1} and ${changelist} properties within the versiontag. This feature may be sufficient for your purpose if, for example you want to incorporate the Git branchname into the version for a CI build job. See Maven CI Friendly Versions
从maven-3.5.0开始,版本标签中支持 ${revision}、${sha1} 和 ${changelist} 属性。例如,如果您想将 Git 分支名称合并到 CI 构建作业的版本中,则此功能可能足以满足您的需求。查看Maven CI 友好版本
Basically, in your pom.xml replace the fixed version by:
基本上,在您的 pom.xml 中,将固定版本替换为:
<version>${revision}${changelist}</version>
Set default values for revisionand changelistin the project root dir by creating a file .mvn/maven.config
containing:
通过创建包含以下内容的文件,为项目根目录中的修订和更改列表设置默认值.mvn/maven.config
:
-Drevision=1.2.3
-Dchangelist=-SNAPSHOT
Check this file into version control, update it when you bump your project revision.
将此文件检查到版本控制中,当您遇到项目修订时更新它。
In your CI system you can then override the changelistvariable using a cleaned-up representation of the Git branch name, eg.
在您的 CI 系统中,您可以使用 Git 分支名称的清理表示覆盖更改列表变量,例如。
BRANCHNAME=$(git rev-parse --abbrev-ref HEAD | sed -E -e 's@[^0-9A-Za-z.-]+@-@g')
mvn clean install -Dchangelist="-${BRANCHNAME}"
(You may prefer git symbolic-ref --short HEAD
for fetching the branchname, YMMV)
(您可能更喜欢git symbolic-ref --short HEAD
获取分支名称,YMMV)
Your artifact built by the CI system for branch feature/branchname
will then have a versioned-branch suffix like:
由 CI 系统为分支构建的工件feature/branchname
将具有版本化分支后缀,例如:
yourproject-1.2.3-feature-branchname.jar
whilst developers who do not use any overrides will still build it as:
而不使用任何覆盖的开发人员仍将其构建为:
yourproject-1.2.3-SNAPSHOT.jar
回答by Chronial
Have you tried using this plugin?: https://github.com/ktoso/maven-git-commit-id-plugin. You can configure it to generate a properties file with all the relevant info about your repo state:
您是否尝试过使用此插件?:https://github.com/ktoso/maven-git-commit-id-plugin。您可以将其配置为生成一个属性文件,其中包含有关您的 repo 状态的所有相关信息:
- branch
- describe
- commitId
- buildUserName
- buildUserEmail
- buildTime
- commitUserName
- commitUserEmail
- commitMessageShort
- commitMessageFull
- commitTime
- 分支
- 描述
- 提交编号
- 构建用户名
- 建立用户邮箱
- 构建时间
- 提交用户名
- 提交用户邮箱
- 提交短消息
- 提交消息完整
- 提交时间
回答by khmarbaise
Have you checked the buildnumber-maven-pluginwhich gives you the opportunity to use the revision number of git. But you needed something different. Furthermore i would suggest to do a thing like:
您是否检查了buildnumber-maven-plugin,它使您有机会使用 git 的修订号。但你需要一些不同的东西。此外,我建议做这样的事情:
1.0.0-SNAPSHOT
1.0.0-SNAPSHOT
beeing on master
蜂拥而至
on a branch you can simple change the version to
在分支上,您可以简单地将版本更改为
1.0.0-BF-SNAPSHOT