Maven Git Versioning Extension 
This extension can virtually set project version and properties, based on current Git status.
- Get rid of...
- editing
pom.xml - managing project versions with within files and Git tags.
- Git merge conflicts.
- editing
- Highly customizable configuration, see example below.

Usage
3.6.3
Add Extension to Maven Project
create or update ${rootProjectDir}/.mvn/extensions.xml file
<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.0.0 https://maven.apache.org/xsd/core-extensions-1.0.0.xsd">
<extension>
<groupId>me.qoomon</groupId>
<artifactId>maven-git-versioning-extension</artifactId>
<version>6.4.3</version>
</extension>
</extensions>
Configure Extension
You can configure the final version format for specific branches and tags separately.
Create ${rootProjectDir}/.mvn/maven-git-versioning-extension.xml.
Example: maven-git-versioning-extension.xml
<configuration xmlns="https://github.com/qoomon/maven-git-versioning-extension" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://github.com/qoomon/maven-git-versioning-extension https://qoomon.github.io/maven-git-versioning-extension/configuration-6.4.0.xsd">
<branch>
<pattern>main</pattern>
<versionFormat>${version}</versionFormat>
</branch>
<branch>
<pattern>feature/(.+)</pattern>
<versionFormat>${1}-SNAPSHOT</versionFormat>
</branch>
<tag>
<pattern>v([0-9].*)</pattern>
<versionFormat>${1}</versionFormat>
</tag>
</configuration>
-
optional
<disable>global disable(true)/enable(false) extension.- Can be overridden by command option, see (Parameters & Environment Variables)[#parameters-&-environment-variables].
-
optional
<updatePom>global enable(true)/disable(false) version and properties update in original pom file.- Can be overridden by command option, see (Parameters & Environment Variables)[#parameters-&-environment-variables].
-
optional
<preferTags>global enable(true)/disable(false) prefer tag rules over branch rules if both match. -
<branch>specific version format definition.<pattern>An arbitrary regex to match branch names (has to be a full match pattern e.g.feature/.+)<versionFormat>An arbitrary string, see Version Format & Placeholders<property>A property definition to update the value of a property<name>The property name<valueFormat>The new value format of the property, see Version Format & Placeholders
- optional
<updatePom>Enable(true) or disable(false) version and properties update in original pom fill (will override global<updatePom>value) -
⚠ considered if...- HEAD attached to a branch
git checkout <BRANCH> - Or branch name is provided by environment variable or command line parameter
- HEAD attached to a branch
-
<tag>specific version format definition.<pattern>An arbitrary regex to match tag names (has to be a full match pattern e.g.v[0-9].*)<versionFormat>An arbitrary string, see Version Format & Placeholders<property>A property definition to update the value of a property<name>The property name<valueFormat>The new value format of the property, see Version Format & Placeholders
- optional
<updatePom>Enable(true) or disable(false) version update in original pom fill (will override global<updatePom>value) -
⚠ considered if...- HEAD is detached
git checkout <TAG> - Or tag name is provided by environment variable or command line parameter
- HEAD is detached
-
<commit>specific version format definition.<versionFormat>An arbitrary string, see Version Format & Placeholders<property>A property definition to update the value of a property<name>The property name<valueFormat>The new value format of the property, see Version Format & Placeholders
-
⚠ considered if...- HEAD is detached
git checkout <COMMIT>and no matching version tag is pointing to HEAD
- HEAD is detached
Format Placeholders
versionFormat will be slugified automatically, that means all / characters replaced by -
${name:-DEFAULT_VALUE}
e.g ${env.BUILD_NUMBER:-0} or ${env.BUILD_NUMBER:-local}
${name:+OVERWRITE_VALUE}
e.g ${dirty:-SNAPSHOT} resolves to -SNAPSHOT instead of -DIRTY
-
${ref}- current ref name (branch name, tag name or commit hash)
-
${ref.slug}- like
${ref}with all/replaced by-
- like
-
${branch}(only available within branch configuration)- The branch name of
HEAD - e.g. 'master', 'feature/next-big-thing', ...
- The branch name of
-
${branch.slug}- like
${branch}with all/replaced by-
- like
-
${tag}(only available within tag configuration)- The tag name that points at
HEAD, if multiple tags point atHEADlatest version is selected - e.g. 'version/1.0.1', 'v1.2.3', ...
- The tag name that points at
-
${tag.slug}- like
${tag}with all/replaced by-
- like
-
${commit}- The
HEADcommit hash - e.g. '0fc20459a8eceb2c4abb9bf0af45a6e8af17b94b'
- The
-
${commit.short}- The short
HEADcommit hash (7 characters) - e.g. '0fc2045'
- The short
-
${commit.timestamp}- The
HEADcommit timestamp (epoch seconds) - e.g. '1560694278'
- The
-
${commit.timestamp.year}- The
HEADcommit year - e.g. '2021'
- The
-
${commit.timestamp.month}- The
HEADcommit month of year - e.g. '01'
- The
-
${commit.timestamp.day}- The
HEADcommit day of month - e.g. '01'
- The
-
${commit.timestamp.hour}- The
HEADcommit hour of day (24h) - e.g. '01'
- The
-
${commit.timestamp.minute}- The
HEADcommit minute of hour - e.g. '01'
- The
-
${commit.timestamp.second}- The
HEADcommit second of minute - e.g. '01'
- The
-
${commit.timestamp.datetime}- The
HEADcommit timestamp formatted asyyyyMMdd.HHmmss - e.g. '20190616.161442'
- The
-
Pattern Groups- Contents of group in the regex pattern can be addressed
${GROUP_NAME}or${GROUP_INDEX} ${GROUP_NAME.slug}or${GROUP_INDEX.slug}- like
${GROUP_NAME}or${GROUP_INDEX}with all/replaced by-
- like
- Examples
- Named Group
<branch> <pattern><![CDATA[feature/(?<feature>.+)]]></pattern> <versionFormat>${feature}-SNAPSHOT</versionFormat> </branch>
- Group Index
<tag> <pattern>v([0-9].*)</pattern> <versionFormat>${1}</versionFormat> </tag>
- Named Group
- Contents of group in the regex pattern can be addressed
-
${version}versionset inpom.xml- e.g. '1.0.0-SNAPSHOT'
-
${version.release}- like
${version}without-SNAPSHOTpostfix - e.g. '1.0.0'
- like
-
${dirty}- if repository has untracked files or uncommitted changes this placeholder will resolve to
-DIRTY, otherwise it will resolve to an empty string.
- if repository has untracked files or uncommitted changes this placeholder will resolve to
-
${dirty.snapshot}- if repository has untracked files or uncommitted changes this placeholder will resolve to
-SNAPSHOT, otherwise it will resolve to an empty string.
- if repository has untracked files or uncommitted changes this placeholder will resolve to
-
${value}- Only available within property format- value of matching property
-
${env.VARIABLE}- value of environment variable
VARIABLE
- value of environment variable
Parameters & Environment Variables
-
Disable Extension
- Environment Variables
export VERSIONING_DISABLE=true
- Command Line Parameters
mvn ... -Dversioning.disable=true
- Environment Variables
-
Provide branch or tag name
- Environment Variables
export VERSIONING_GIT_BRANCH=$PROVIDED_BRANCH_NAMEexport VERSIONING_GIT_TAG=$PROVIDED_TAG_NAME
- Command Line Parameters
mvn ... -Dgit.branch=$PROVIDED_BRANCH_NAMEmvn ... -Dgit.tag=$PROVIDED_TAG_NAME
ℹ Especially useful for CI builds see Miscellaneous Hints - Environment Variables
-
Update
pom.xml- Environment Variables
export VERSIONING_UPDATE_POM=true
- Command Line Parameters
mvn ... -Dversioning.updatePom=true
- Environment Variables
-
Prefer Tags for Versioning instead of Branches
- Environment Variables
export VERSIONING_PREFER_TAGS=true
- Command Line Parameters
mvn ... -Dversioning.preferTags=true
- Environment Variables
Provided Project Properties
git.commite.g. '0fc20459a8eceb2c4abb9bf0af45a6e8af17b94b'git.refvalue of branch or tag name or commit hashgit.ref.sluglikegit.refwith all/replaced by-
git.branche.g. 'feature/next-big-thing', only set for branch versioninggit.branch.sluglikegit.branchwith all/replaced by-
git.tage.g. 'v1.2.3', only set for tag versioninggit.tag.sluglikegit.tagwith all/replaced by-
git.commit.timestampe.g. '1560694278'git.commit.timestamp.datetimee.g. '2019-11-16T14:37:10Z'git.dirtyrepository's dirty state indicatortrueorfalse
Miscellaneous Hints
Enable Debug/Trace Logging for extension
mvn ... -Dorg.slf4j.simpleLogger.log.me.qoomon.maven.gitversioning=debug
Commandline To Print Project Version
mvn help:evaluate -Dexpression=project.version -q -DforceStdout
Reproducible builds
The reproducible builds feature (https://maven.apache.org/guides/mini/guide-reproducible-builds.html) newly introduced in maven can be easily supported with this extension by using the latest commit timestamp as build timestamps.
<project.build.outputTimestamp>${git.commit.timestamp.datetime}</project.build.outputTimestamp>
IntelliJ Setup
For a flawless experience you need to disable this extension during project import. Disable it by adding -Dversioning.disable=true to Maven Importer VM options (Preferences > Build, Execution, Deployment > Build Tools > Maven > Importing > VM options for importer).
CI/CD Setup
Most CI/CD systems do checkouts in a detached HEAD state so no branch information is available, however they provide environment variables with this information. You can provide those, by using Parameters & Environment Variables. Below you'll find some setup example for common CI/CD systems.
GitHub Actions Setup
execute this snippet before running your mvn command
if [[ "$GITHUB_REF" = refs/tags/* ]]; then
export VERSIONING_GIT_TAG=${GITHUB_REF#refs/tags/};
elif [[ "$GITHUB_REF" = refs/heads/* ]]; then
export VERSIONING_GIT_BRANCH=${GITHUB_REF#refs/heads/};
elif [[ "$GITHUB_REF" = refs/pull/*/merge ]]; then
export VERSIONING_GIT_BRANCH=${GITHUB_REF#refs/pull/};
fi
GitLab CI Setup
execute this snippet before running your mvn command
before_script:
- export VERSIONING_GIT_TAG=$CI_COMMIT_TAG;
export VERSIONING_GIT_BRANCH=$CI_COMMIT_BRANCH;
Jenkins Setup
execute this snippet before running your mvn command
if [[ "$GIT_BRANCH" = origin/tags/* ]]; then
export VERSIONING_GIT_TAG=${GIT_BRANCH#origin/tags/};
else
export VERSIONING_GIT_BRANCH=${GIT_BRANCH#origin/};
fi
Build
- mvn install
# run integration tests after install,
# integration tests will run with LATEST version of extension installed
- mvn failsafe:integration-test