Friday, September 28, 2012

Version Control Branching and Versioning

In a VCS (Version Control System) there are some basic concepts that I am not going to cover like check out, merge, update, etc.  What I am going to rant about is how and when to branch/version, and what the different type of directories are for.  Also, please note that these are my ideas, and may not be held generally.  Also, please note that I have over ten years of experience with VCS including CVS, SVN, and Bazaar.

In simple terms each 'project' has a base directory.  Inside of that, among other things, are three VCS directories: trunk, versions, branches.  (You will often see some repository specific files here as well, but you should be able to ignore those for general use.)

trunk - This is the 'home base'.  All new significant branches come from here, and all production features get merged into it.  It is possible to have features that only exist in branches, and some of those may actually be deployed and used in 'production', but if they are not merged back to trunk they are not considered part of the core code.

versions - These are production snapshots that are 'released' or deployed into a production environment.  Once a version is created it should only be updated with bug fixes and minor release.

branches - These are temporary copies of the version or trunk.  Here the work is actually done and tested before the code is pushed back to trunk.

Aside:
- bugs that 'escape' into a production release should be 'patched' onto each and every 'supported' release, and then applied to trunk.
- I am only addressing the major / ideal events here.  There are some very complex and subtle interactions that may occur between branches, version, and/or trunk.

To explain my preferred way of versioning and branching I am going to use a completely manufactured, but common, example situation.

In this example a software company has an application.  The application is large enough and has enough developers working on it at any one time that it would create confusion and major confilcts if not handled properly.

This company is preparing to create a new version of their software.  It will be the fifth major release of their software.  So first, trunk is branched into something like branches/5, branches/v5.0, etc.  As time goes on new tasks are branched from that or from trunk itself.  Where they are branched from is completely dependent on what release they are target for.  So, a developer that has added some functionality to be released with version 5 would branch branches/5 into a branched named something like branches/5-QuickInventory, branches/5-13235, etc...  At the same time a developer might be assigned to develop a feature that would go into some future release.  That developer would branch trunk into something like branches/RestInterface, branches/11564, etc...

As tasks/branches are competed they are merged back into the base from which they started.  Once all of them are merged in the base, branches/5 in this case would be merged into trunk and either moved (or re-branched from trunk) to become versions/5.


  1. Project Created: /projects/falcon
  2. VCS set up: /projects/falcon/trunk, /projects/falcon/branches, /projects/falcon/versions
  3. Major Release Cycle
    1. Version identified
    2. /projects/falcon/trunk branched to /projects/falcon/branches/1.0
    3. /projects/falcon/branches/1.0 branched into development branches:
      1. /projects/falcon/branches/1.0-100
      2. /projects/falcon/branches/1.0-101
      3. /projects/falcon/branches/1.0-102
    4. development branches merged back into /projects/falcon/branches/1.0
    5. /projects/falcon/branches/1.0 merged back into /projects/falcon/trunk
    6. /projects/falcon/branches/1.0 moved to /projects/falcon/versions/1.0
  4. Maintenance/Minor Release Cycle
    1. /projects/falcon/versions/1.0 branched into /projects/falcon/branches/1.1
    2. development branches created:
      1. /projects/falcon/branches/1.1-234
      2. /projects/falcon/branches/1.1-237
      3. /projects/falcon/branches/1.1-238
    3. development branches merged back into /projects/falcon/branches/1.1
    4. /projects/falcon/branches/1.1 copied to /projects/falcon/versions/1.1
    5. /projects/falcon/branches/1.1 merged back into /projects/falcon/versions/1.0
    6. /projects/falcon/versions/1.0 merged back into trunk
Goals:
  1. Always be able to build every 'supported' version at any time.
  2. Prevent features (code) from being lost.
  3. Prevent code regression