Versioning strategies for the sane

I don’t know why I didn’t think of this one earlier, it makes so much sense.  A coworker of mine shared a fantastic assembly versioning strategy that eliminates all of the decisions about major/minor version numbers we have to make up.

If I’m not shipping an assembly for a product, the actual version of an assembly doesn’t matter for any kind of marketing reasons.  For AutoMapper, the version numbers do indicate the level of feature increments, and we see this with products like jQuery, the .NET Framework etc.

However, if I’m building something where no one cares if the version is 1.0 or 2.0, then we can embed a little more information that might actually be useful to us.  We can tag the assembly with a changeset hash to determine exactly which commit this assembly was built from.  But that still leaves us to make up something for the actual assembly version.  But my buddy Glenn shared this brilliant strategy: use a format based entirely on dates, that always increases, is easy to read and understand, and never hits any kind of wonky overflow exceptions:

Brilliant.  So today it would be:




Because it uses a sortable date format, I guarantee that my version numbers always go up.  With a timestamp, I can easily tell when the build was, so it’s easy to know when a piece of software was last deployed and what changes are in production.  With whatever automated build you use (psake, NAnt, Albacore, Rake, whatever), it’s trivial these days to spit out an AssemblyInfo.cs file that’s built with all of your projects.

Pretty sweet, just wish I did this years ago.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in C#. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • isee

    nice one.
    what’s the 2110 for ?

  • Matthys Meintjes

    I use the same type of versioning system, but instead of just using the date, I add the latest database migration file version number in front – ..


    This makes it easy to see database compatibility between versions – if it starts with the same number, then the database is the same.

  • Nathan Evans

    You’re kind of buggered though if you want to run off a new build of a release from last year.

    It is a viable versioning strategy provided your project sits on just the trunk and never branches.

  • Nice idea, just added it to our app :)

    When we talk about web apps it has nice usage – the version number of app as parameter for css and js files.
    Additionally we added a place holder $$VERSION$$ in our css file for all images (url) and our build server is nicely replace it with current date time :)

    2110 means hour and minute (21:10) – the assembly version accepts in AssemblyInfo.cs accepts only four version parts


  • @Nathan

    Funny, we always feature branch. But we do have concepts of trunk/release branches. We never release from a feature/defect branch, because that means it isn’t integrated into a production branch.

    This is a strategy to help with deployment, not development.

  • Martin

    It gets a little bit problematic once you introduce branches and have to build/deploy patches for old versions.

    I use a slight variation of that strategy, which uses only the first three parts of the version number and goes like this:


    - “2010.5.1025″ would be version 2010.5 (fifth major release of 2010, built on Oct-25 (1025).
    - “2011.1.0201″ would be version 2011.1 (first release of 2011, built on Feb-01)

    Assume we now have to deploy a patch for version 2010.5. This would become “2010.5.1423″
    It’s still the fifth release of 2010, but the patch was built on the 23th day of the 14th month of 2010 :-) .

    Hope this makes sense.

  • Steve

    The problem with this strategy is it isn’t self evident how extensive the changes are. Say you are on verison 5.1.0.X of a software, and there is some minor bug fixes, often you’d version it up to 5.1.1.X. If there are new (semi-major) features, you’d move it to 5.2.0.X, and finally if it’s an entire new version, 6.0.0.X.

    With your verisoning system, all three would be treated

  • Not that it comes up often, but if you use this version number in the Windows Installer, Windows Installer (for reasons only known to them) only looks at the first 3 numbers. So if the installer were to have any auto-upgrade logic, that logic would not work for multiple builds on the same day.

  • Hi Jimmy, this is a very good idea. The guys from Nuget use a similar strategy that is in the same lines but still allow you to have a Major and Minor versions. Their format is


    The date is not a real date though (it wouldn’t fit the 65535 size limit). The DATE is (DateTime.Now.Year-InitialYear)MMdd. So if your start year is 2010 and todays is 2011-02-23 your version number would be something like:

    It’s not as straight forward to read the date as yours but you can still read it plus you get the advantage of keeping the Major, Minor e Build numbers.

  • Chris

    I’ve been doing it that way for years and mainly for the sortability of it. I however use dashes instead of periods as I’ve found that some OS’s have issues with periods in the file name, though now a days it may not be as big of an issue.

    It also works better (IMO) for use in URL’s.


  • Nice, but not semantic versioning compatible ( )

  • @Steve

    That’s where your versioning is more appropriate. For products/libraries where version numbers convey information to the users, then the information needs to be relevant to the users :)


    I don’t think I have that choice with .NET version numbers, I have to specify 4 numbers, and the dots are just a formatting issue.


    If I have users that care about semantic versioning, I’d go that route. For lots of internal applications, no one cares that uses the app, but for people building/maintaining the app, it’s more important the what/when.

  • At my last gig, we completely separated the concept of the project/assembly version from the concept of the release number. We went a similar route as you describe for the project/assembly version, and then used numbers like 1.0, 1.5, 2.0 etc… for the release numbers.

  • I love it. Might even help teams get away from thinking in terms of big major or minor releases and move towards smaller, regular releases.

  • Edwin G. Castro

    Additional comment on Windows Installer: The “major” and “minor” portions of the ProductVersion for a Windows Installer package must not exceed 255. The “build” portion of the ProductVersion for a Windows Installer package must not exceed 65,535. As mentioned previously, Windows Installer will ignore the fourth component (“release”). The assemblies contained within your Windows Installer package can have any AssemblyVersion you like though so this strategy cannot be used in the ProductVersion of the MSI package only.

  • Well NuGet cares about the version number and even makes decisions based on the version. Of course, in our case, we only care about the version of the package and not the assemblies inside.

    But a lot of people version their packages after their assembly. For details on how we factor that in, there’s a 3 part series by Ebbo about how we handle versioning. I think Part 2 or 3 is the relevant part, but the other parts set up the context.

    NuGet doesn’t follow SemVer exactly, but recommends it. NuGet is considerably more conservative because we don’t expect that everyone is following semver, but expect most people follow the major, minor, etc. semantics.

  • This idea fits very neatly for some of the stuff I’m working on and it turns out it’s really easy with the MSBuild Community Tasks, thanks for the suggestion.

  • David Liebeherr

    Hi Jimmy,
    thank your for this idea for a version strategy.

    It is a very nice idea, but unfortunatelly it has one huge problem:
    Assume you have multiple branches in your version control system like a trunk and a brnach for every major version of your product.
    Now you have to make a bug fix for the product in the branch of the major version from last year.
    When you build this branch all the assemblies will have a version starting with the current year.
    But in this case it’s still the product with the major version of last year.
    Even worse, the bug fixed build will now look more recent than the build in the trunk.

    So the startegy you mentioned is still nice and usefull for small projects, but it will ead to serios problems when used for larger projects or products.

    Anyway, thanks for sharing your thoughs on this topic!