Agile Versioning – Managing Version Numbers Between Sprints

agilescrumsprinttestingversioning

My question is a little bit about branching, versioning and agile development in general, but the heart of all three is the version number I think.

Currently, I'm using internal version numbers (e.g. 1.0.4). This is also what the QA gets. But what if we would need a hotfix? I can't use the third number anymore, because it is already used. So I need another mechanism. But how do you tag or create your branches for each sprint? What is the version you use?

I need a replicable version number/branch/tag for QA, but I also need to bug fix it on the same version if necessary. The customer should never see the internal version numbers. Instead he gets e.g. 1.1.

A secondary issue is how to prevent waiting time between sprints. E.g. the developer has already finished, but the QA is still testing. Does the developer begin with tasks from the next sprint? Or what is if the developer and the tester have already finished their work. They shouldn't wait one week for the beginning of the next sprint. Or if a feature can't be finished in one sprint or the bugfixing thereof …

Is continous testing and creating a working release in a sprint a requirement for agile development? Is the build number the only thing what the testers get? I can't use the build number, because Jenkins only stores the last 5 builds (and later it is not possible anymore to restore this version, except if it is somehow tagged). Should I use commit ids instead? Also no new features should be added, when giving the QA a bugfixed version.

Best Answer

I've used the notion of a release candidate for that purpose.

I assume you need a unique version number for every set of deliverables that you release towards QA. Lets do an example:

You are starting sprint 5. The version you are working off of in sprint 5 is 1.0.0. You expect this release to be a feature release so the version for the software after sprint 5 would be 1.1.0; therefore, the team is currently working on 1.1.0-RC1.

The team finishes the last story in sprint 5. You assign the Version 1.1.0-RC1 to that commit/revision. The deliverables for 1.1.0-RC1 go to QA and they come back with 3 bugs which can be fixed within the remaining 2 days in sprint 5.

However, other team members have already begun working on sprint 6. You need a new VCS branch here! Since you expect sprint 6 to be another feature release, sprint 6 would yield version 1.2.0; so these team members are working on 1.2.0-RC1.

The bugfixes (that resulted from testing 1.1.0-RC1) have to be done in another branch. The version they go into is 1.1.0-RC2.

Work on 1.1.0-RC2 is done (that means: all known issues are fixed). The deliverables for 1.1.0-RC2 pass QA. The same commit as 1.1.0-RC2 in your VCS (or a new one if you keep the version number under version control) becomes 1.1.0. That version is what you use towards the customer / end users.


You basically keep increasing the -RC number until QA is satisfied with the deliverables. The most recent RC is the same code version that you can ship without the -RC suffix.

If you expect more than 10 RCs for a sprint (which you shouldn't; that'd be too many bugs if you ask me) you should use leading 0s for the RC number. That makes sure the version numbers are sorted chronologically, e.g. 1.1.0-RC01 through 1.1.0-RC26.


As to when the work from a sprint is not to be released to end users: i'd just keep on versioning as if you would release. This will of course create gaps in the public version history but thats totally fine IMHO.
If management wants a consistent public version number i'd still keep on labelling my versions as if i released at every iteration; maybe with an -INT suffix. And at the same time keep a mapping of internal and public versions. Somewhat like this:

 o @1.1.0-INT @1.1.0
 |
...
 |
 o @1.2.0-INT
 |
...
 |
 o @1.3.0-INT
...
 |
 o @1.4.0-INT @1.2.0

If you choose that route make sure that everyone involved (development team, management, support staff, marketing people, ...) are aware of this and know how to look up the interal<->external mapping whenever they feel like it. Otherwise, ... you can imagine.


On branching

I strongly suggest that you branch RC2 off of RC1 and continue with 1.2.0 in the main branch (e.g. develop in git flow). When 1.1.0 passes QA you can merge it back into the main branch. Here is a bunch of git graphs showing how you could implement what i described above with git flow:

All stories for 1.1.0 complete; you tag the head of develop with 1.1.0-RC1. Work on 1.2.0 continues in develop

 o branch develop @1.0.0
 |
... implement stuff
 |
 o @1.1.0-RC1
 |
 o
 |
 o

When the QA result for 1.1.0-RC1 comes in you branch off for 1.1.0-RC2. Work can then continune in parallel. You can merge the final RC of 1.1.0 back into your main branch once QA for that passes (or ealier if there is another urgend need).

 o @1.0.0
 |
...
 |
 o @1.1.0-RC1
 |\
 o o branch release/1.1.0-RC2
 | |
 o o
 | |
 o o @1.1.0-RC2 @1.1.0
 |/
 o merge release/1.1.0-RC2 into develop
 |
 o @1.2.0-RC1

In Git flow you'd not tag the version in the realease/* branch but rather merge that into master and tag that commit with 1.1.0.