I found that for big or medium size teams git flow is quite practical. What I didn’t like about it, is that it requires to change the version all the time you change the branch in your repository. At some point I took responsibilities of release engineer in our team. Since I’m very lazy to do all of this styff I came up with some Scala code in the
project catalog of my current working project. Later I rewrote it as an sbt plugin.
So, what can it do for you?
Let’s start with git flow. The typical git flow process have following branches:
master- contains stable releases. Only tested releases are merged here, and only stable artifacts are build from this branch (no snapshots allowed).
develop- current development release. Features for the next release are going here. We can define the version as a next minor version: “(last version + 0.1)-SNAPSHOT”.
release/x.y.z- release branches. These branches are for upcoming releases during stabilization. In our team we do not have
developbranch, but several
releasebranches. For me, it’s more clear. The versions on this branch is
feature/xxx, and also
hotfix/zzz- branches for a specific task development. The version for such build
You might see that we need three components to compose the version:
The main setting of sbt-git-flow-version is
versionPolicy which has type
Seq[(BranchMatcher => VersionCalculator)]. So it tries to find matching rule for a branch and calculate a version.
What is a
BranchMatcher? It’s a function
String => Option[Matching] where matching is a case class containing branch name and some additional optional extracted string. There are several predefined branch matchers:
exact(name: String)- branch name is equals to
name, extraction is empty.
prefix(prefix: String)- branch name starts with
prefix. The part after prefix is extraction.
prefixes(prefixes: String*)- same as prefix but supports a number of prefixes.
regex(r: String)- branch name matches regular expression
r. If the expression contains groups, the first group will be returned as extraction.
any- matches any branch (might be used to define default behaviour).
VersionCalculator converts previous version, current version, and matching either to the version number or error message. The predefined version calculators are:
currentTag- take a version from a current tag. If there are several current tags it will take the one with a maximal version.
nextN- increment major, minor, build or n-th number of a last version. The version is snapshot by default.
matching- take a version from matching returned by
BranchMatcher. The version is snapshot by default.
lastVersion- previous version. Version value is taken from last tag or
initialVersionsetting. The version is not snapshot by default.
lastVersionWithMatching- takes last version and append matching returned by
BranchMatcher. By default new version is snapshot.
unknownVersion- fails with unknown version message.
The default policy is defined as:
Seq(exact("master") -> currentTag(), exact("develop") -> nextMinor(), prefix("release/") -> matching(), prefixes("feature/", "bugfix/", "hotfix/") -> lastVersionWithMatching(), any -> unknownVersion)
What literally means following:
1.4.2, the current version is
release/2.12.85the version is
feature/123-new-uiand the prevous version “1.0.1” the current version is
You can define your own rules in you
build.sbt in the following way:
import sbtgitflowversion.BranchMatcher._ import sbtgitflowversion.VersionCalculator._ versionPolicy := (exact("big-release") -> next-major()) +: versionPolicy.value
This will set the next major version for the “big-release” branch.
Current verion of the plugin is
0.1. So, to add to your
project/plugins.sbt the line:
addSbtPlugin("me.limansky" % "sbt-git-flow-version" % "0.1")