Thursday, September 29, 2011

Mercurial branching

The blog is now moved here

I have been working with git for awhile and found git very powerful. Our team was forced to use mercurial so we needed a branching model. We used this branching model with git which I found very useful. I didn't find really step-by-step guide of how to deal with mercurial after some research.


I was inspired by A Guide to Branching in Mercurial and tried to implement git practices with mercurial. The model itself is really similar to git's one. The purpose of this post is to describe how to implement that model with mercurial.




Here is really cool diagram of how it looks like


1. Core branches

Similar to git's model there are two main branches  develop and master. Those branches hold the last stable development and production-ready snapshots respectively. You should create those branches initially and forget about default forever:

hg branch master 
Note, branch would be created upon the first commit.
hg ci -m "Creating master branch"

Now your current branch is master. You can check it by executing hg branch with no arguments. Now let's create develop branch:

hg branch develop
hg ci -m "Creating develop branch"

Ok, now we have two branches with two HEADs which point to the latest changesets in develop and master branches.

Now we should push our branches to remote repository.

hg push --new-branch

Mercurial's branches are really differ from git's so they are not just a reference to a commit object, but mercurial's branch is a part of changeset object metadata. The changeset object with no children is called HEAD. To make a parallel development you should be able to have multiple HEADs in your repository. In fact you should have one HEAD per branch.
Mercurial may warn you while creating new HEAD unless you specify -f option while pushing. Use -f in this case because new HEAD is what you need here. Here is short discussion about this.


2. Feature branches

Those are used to make actual development of new features. The idea is to make feature branch from develop and merge back to develop once the feature is completed. To create branch from develop you have to switch to it first:

hg up develop

Now you are on develop branch.

hg branch feature-acoounts
hg ci -m 'Creating new accounts branch'
You can skip committing branch right now and keep on making development. The branch would be created once you make your first commit. But I suggest to do this because it is very possible to forget to commit. You can switch to another branch for some reason and forget to switch back. Anyway, I found creating simple commit for creating new branch just safe.

Now you can do development and make commits on a road. You can even push your branch to remote:

hg push -b feature-accounts
I found such pushes useful if you continue development from different PC.
Once development of a new feature is done you want to merge it to the develop. Note, your working directory should be clean and there should not be any uncommited changes.

hg ci -m "Closing accounts branch" --close-branch
now branch feature-accounts closed
hg up develop
switched to deveop
hg merge -r feature-accounts
branches merged
hg ci -m 'Merge feature-acoounts into develop'
merge commited
hg push -b develop


3. Release branches

The purpose of release branches is perfectly described in this post. Release branches is for beta testing before going to production. release branch is created from develop and merge back to include all the bug fixes back to development version.

hg up develop
hg branch release-1.2
making bug fix. commuting changes.
hg up develop
hg merge -r release-1.2

After all the beta testing  is done release-1.2 branch could be merged to master and tagged if necessary.

hg up master
hg merge -r release-1.2

Note, the difference between master and release is that master is for production-ready state and release for pre-release testing.


4. Hot fixes branches

Sometimes it is necessary to make a bug fix directly on live server. Obviously you can't do those fixes in develop because you have other features there which are not ready to publish on production. In this case you should create a branch directly from master make changes and merge back to master  and develop afterwards. 

hg up master
hg branch hotfix-ie8-bug
making some bugfixes
hg ci -m 'IE8 bug fixed' --close-branch
hg up master
hg merge -r hotfix-ie8-bug
hg ci -m "Merged hotfix-ie8-bug into master"
hg push -b master --new-branch
now merging to develop

hg up develop
hg merge -r hotfix-ie8-bug
hg ci -m "Merged hotfix-ie8-bug into develop"
hg push -b develop


Looks pretty the same as feature branches. The only difference is that we created branch from master and merged it back to master.


Closing branches

You should always close feature, bug and hotfix branches once they are done. Mercurial provides an option to a commit. Ensure you are now in the branch you want to close

hg branch
feature-accounts
hg ci -m "closing branch accounts" --close-branch

Now branch is closed.
Mercurial can ask you to pass -f option while pushing this changeset because it actually creates a head. Go ahead and make hg push -f 

Summary

Mercurial is good enough to make development and it's branches are better then they seem. Hopefully this post was helpful to understand how to deal with mercurial branches. 

No comments:

Post a Comment