Version numbers are that magical, though somewhat mysterious, number that seems to be attached to all software products. Sometimes they're one big long number, sometimes they're dates, and still other times they're a combination of seemingly meaningless numbers, letters, and dots. It all basically boils down to a need for developers to know what features (and bugs) are contained in that particular piece of software. As bugs are patched and new copies of the software are released or existing installations are patched, developers need a way of knowing exactly what is in that installation. Without this magical number, developers would have to contend with a possibly infinite number of installations whose feature sets are simply unknown.
I have several projects that whose source is controlled in
Handling version numbers is more complex than just putting a series of numbers together with dots. There are more than a few software developers that endure a hellish frustration of lining-up version numbers for various required libraries for their projects in order to make it all work properly. The most important part about giving each version of your software a unique, serialized form: every new release gets a higher number than the previous one.
Determining what version number a particular project should start with really isn't terribly important. If it is a brand-new project, I recommend starting at version 0.1: this indicates that it is new and still under construction; version 1.0 should be the first stable version recommended for the public. Of course, there have been many very functional pieces of software that were very functional prior to making that "magical" 1.0: it is up to you (and/or your company's management/marketing departments) to determine what versioning scheme works best for you.
My methodology involves two main elements with two optional elements. The version number layout is major.minor(.maintenance-typeNUM). The first segment is the major version number: in a 1.0 release, the major version is 1, and the minor version is 0; the optional maintenance version is left out and assumed to be 0, and the type+NUM is left out completely.
Major Version Number
This number for me starts out at zero for the initial inception of a project. If it's an existing project that is just receiving it's first official version number, I generally give it a much higher number, or start out with 1.0 (a new version would then be 2.0). This could also be set based on the number of years it's been running or the number of major revisions you believe it's been through (in case of the latter, I suggest adding one just in case there was one you can't recall). If it starts higher than 1, I recommend keeping it below 10 as higher version numbers seem to confuse and worry people.
Changing the major version should be a fairly rare thing and involve massive backend and frontend changes. Where upgrades are concerned, this generally involves a more complex manner of reloading data and "simple" modification of existing data (i.e. database stuff) simply isn't feasible.
Minor Version Number
Anytime the major version number increases, this should switch to zero (i.e. "1.2" to "2.0"): that seems pretty obvious, but there are some that simply don't grasp the relationship between the two numbers. I generally increment this number when a large number of new features are waiting for implementation: the new features are all added into this release (where appropriate). Frequent minor version upgrades seem to generally be accepted as alright, though I would recommend leaving a good amount of time (i.e. at least a month) between these releases.
As the name implies, this is for minor changes. If there is a database schema change, that warrants a new minor version number, though generally that change is coupled with a few other new features and changes. Upgrading from the previous minor version number (as long as the major version remains the same) should be simple and seamless. If there's a change that makes a release incompatible with previous versions then it may need to just become the next major release.
Maintenance Version Number
This is the third portion of the version string, i.e. the "13" in "1.4.13". Major releases generally leave out this number, so version 1.0 actually has a maintenance version of 0 initially (i.e. 1.0.0). As with standard numbering this one is reset to zero anytime the major or minor version is incremented, though sometimes this number continuously increases regardless of major/minor versions: when it is used as a "build number," it is sometimes associated with the last commit version from the SVN repository from which the release was generated on (i.e. an update from "0.9.1395" to "1.0.1500" to "1.1.1985" is okay). Frequent releases with updated maintenance versions is perfectly acceptable as it shows that fixes are being implemented in a steady fashion (just be careful to make sure the customer understands that this means "bugs are getting fixed quickly" and not that "this product has a lot of bugs that we are constantly fixing"; the difference between the two statements is vast in the mind of the customer).
Once again, the name implies this number is updated for maintenance purposes only. Only minor tweaks and code changes should be involved, and absolutely NO schema changes or major rewrites should be allowed. This can involve fixing some items in the database or configuration files, and should always be backwards-compatible. If there's a change that makes it non-backwards-compatible, you're looking at a MAJOR version release.
Releases are occasionally made for the purpose of testing the system: for this we have release types: when I'm working on upgrading from 1.1.x to 1.2, I go through the following cycles: 1.2-ALPHA1, 1.2-BETA1, 1.2-RC1, and then 1.2.0.
Example Version Timeline
Note: Developers would implicitely be testing all versions, even those that don't list them.
Color key: Development only, testers, everybody
Storing Version Information For Your Project
In all of my software projects, I specifically store version information in a single file. Any time a new release is built, that file is modified (first). An example of this file's contents would be:
There are a few very important reasons to do this that are specifically related to Subversion: I'll cover them in the next installment. An important reason that is unrelated to SVN is for comparing code version to the database version.
"What is this 'database version' thing you talk about?"
In order to lineup code features with database layout, it is important to store a version for code and another version for the database. Upgrades can easily affect the database's layout (schema), or bug fixes might automatically move data around in the database to fix the problem. By creating this dual-version, the applications can now automatically perform scripted upgrades that can affect the database. Pull a new version down, and the first time the code is executed, the upgrade system can detect that something has changed and run scripts that will make things friendly to the updated code... but I'm getting ahead of myself: if you're interested in this topic, take a look at CS-WebAppLibs, which has a built-in upgrade mechanism (it is an extension of CS-Content).
That was a lot of stuff to think about. Are your eyes twitching a little? Mine are.
In the next installment, we'll talk in depth about the code repository's role in all this, and why I have chose Subversion to fill this role. We will cover:
I reserve the right to update and/or completely change this page in the future.