A Mercurial Branching Workflow

The StreetHawk code is broken up into multiple repositories, the backend webapp, the iphone UI, the iphone API layer that accesses the database and handles all logical/operational aspects of the iPhone app, the android app (with the same breakdown), tools etc.  Up until now all code has been checked straight into the “default” branch (HEAD).  Going forward we have decided to adopt the following scheme inspired by and based on workflows prescribed by Steve Losh and Vincent Driessen.  I would particularly recommend Steve’s tutorial on branching which was very very critical in helping me understand the general branching techniques in mercurial.  If anything this post is a summary of their article to act as a “manual” for ourselves and is prone to change given all the nasties we may find in the future.

Command Summary

Firstly a recap of some of the branching and tagging commands that we will use later on.

Creating a new branch

# Get into the branch from which the new branch is to be created.  
# This would usually be "default" if it is a new future development or "stable" if a bugfix
hg checkout <parent_branch_name>
# Create the new branch
hg branch <branch_name>
# commit it - at this point it is a local branch
hg commit -m "Added <branch_name> branch"
# push it to the server to create a remote branch
hg push -b <branch_name> --new-branch

Merging from another branch

Time to time you may find the need to merge from another branch.  This is simple.  This will ensure the source_branch is merged into the target_branch.  NOT the other way around (even after you do a push).

# Get into the branch "into" which you want changes merged 
hg checkout <target_branch>
# merge from the source branch
hg merge <source_branch>

Closing a branch

Some times (quite often actually) you may find branches created unnecessary.  To remove the branch:

# Get into the branch you want to close (by now you can see the general pattern here!)
hg checkout <target_branch>
# close it
hg commit --close-branch

Tagging a branch

Tag a branch on every release.  Simply do:

# Get into the branch you want to close
hg checkout <branch_name>
hg tag <tag_name>

The convention used here is: <PUBLIC_VERSION>_<PRIVATE_VERSION>

PUBLIC_VERSION = <MAJOR_VERSION>_<MINOR_VERSION>_<BUGFIX_NUMBER>
PRIVATE_VERSION = <PURPOSE>_<BUILD_NUMBER>
MAJOR_VERSION - indicates a back incompatible version
MINOR_VERSION - new features added
BUGFIX_NUMBER - bugfixes updates
PURPOSE - purpose of the build - eg "APPSTORE", "TESTFLIGHT", "ADHOC" etc...
BUILD_NUMBER - The build attempt for a given PUBLIC_VERSION and purpose.

Branching and Release Workflow

In this scheme we have the following branches:

“default” – This the dev branch that contains all the checked in features and bugfixes that are *ready* to go into the next stable release.

“stable” – The branch that tracks the stable production releases.  Code from “default” is always merged into stable before a release.

“feature_xyz” – New features are added and developed on their own branches (eg feature_camera, feature_location etc) and merged into “default” upon completion but NOT before they are ready to be accepted into are release.  So only merge these into default when they are ready for the next release.

“bugfix_xyz” – Similar to the feature branches but these are usually branched from stable and then merged back into both “default” and “stable”.  These are usually urgent changes/fixes to be applied on released code.

Roles

Given the above branches, an appropriate workflow would contain the following roles (could be the same person):

Developer – Is responsible for adding new features and bug fixes and most likely would be adding to “default” or “feature” branches (or onto stable via bugfix branches).

For example to add the new “awesome” feature, one would do:
# get into default
hg checkout default
# do an update
hg pull -u
# create the feature branch
hg branch feature_awesome
# commit it - at this point it is a local branch
hg commit -m "Added <branch_name> branch"
# add the awesome feature
# do a few commits A, B, C
# push it to the server to create a remote branch ONLY 
# when ready for release
hg push -b <branch_name> --new-branch

Release Creator/Owner – Creates new stable production releases.  Note DO NOT do a rebase here as that would detach local changes.  We specifically want to keep track of all past activity.

# get the latest on all branches
hg pull -u
# get into stable
hg checkout stable
# Merge default into stable to get all production ready 
# features into stable
hg merge default
# Do the testing and when time to release, tag it (you are still in stable)
hg tag <tag_name>
# push the new tag
hg push
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s