Standard Branching
How the Mercurial project itself manages branched development
Contents
1. Introduction
There are many possible workflows for handling branched development in Mercurial, with combinations of multiple repositories, named branches, bookmarks, etc. This page describes the scheme the Mercurial community itself uses, which has several advantages. The basic model is:
- development primarily occurs in the default branch
- bugfixes are made in one or more release branches
- release branches are regularly merged 'upward' to propagate fixes
2. What not to do
First, a list of common mistakes:
- Don't use long-lived branch names for short-lived feature branches
- Don't use a name other than default for your main development branch
- Don't use branch names that are the same as your tag names
3. The default branch
This is where development of new features occurs. This is the branch that will be checked out by default when you clone. If you're starting from an empty repository, this is the branch you'll start in.
It is strongly recommended to do your primary development on the so-called 'default' branch, because it is the branch used by default in various commands such as clone.
4. Release branches
There are some minor differences based on how many release branches you intend to maintain.
4.1. One maintenance branch
If you only intend to maintain one major release at a time, you only need one release branch. The Mercurial project uses the name "stable". This branch is reused from release to release. To first create the branch, simply do something like the following between the time you start your release code freeze and the time you tag your release:
$ hg branch stable marked working directory as branch stable $ hg ci -m 'start code freeze for release 1.0'
For future releases, you simply merge the default branch into the existing release branch rather than creating a new one:
$ hg update stable 44 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg merge default 40 files updated, 0 files merged, 2 files removed, 0 files unresolved (branch merge, don't forget to commit) $ hg ci -m 'start code freeze for release 1.1'
4.2. Multiple maintenance branches
If you intend to maintain multiple major releases in parallel, you will want one branch per major release. Choose a consistent naming scheme like 'release-1.0' that corresponds to releases tagged '1.0', '1.0.1', etc. For each release you should open your new branch when you enter your release code freeze:
$ hg branch release-1.0 marked working directory as branch release-1.0 $ hg ci -m 'start code freeze for release 1.0'
4.3. Timing
We suggest moving to a release branch when you enter code freeze so that it's always clear what the rules are for committing based on the branch name.
5. Applying bugfixes
5.1. Where to apply fixes
Bug fixes should always be committed first to the earliest maintained release branch they apply to. This will allow you to get maximum advantage out of Mercurial's merge intelligence.
5.2. Merging
After one or more fixes have been applied to a release branch, you should regularly merge that branch 'upward' into either the next more recent release branch. This will bring all the changes (ie your fixes) made on the earlier branch since the last merge into the newer branch. Repeat this process until you've merged the latest release into the development branch. This process is known as 'forward porting'.
Example one (single release branch):
- Alice finds a bug in the latest release
- Alice checks out the 'stable' branch
- Alice develops, tests, and commits a fix
- Alice checks out the default branch
- Alice merges with the stable branch, tests again, and commits
Example two (multiple release branches):
- Bob finds a bug in version 1.3.2
- Branches 1.1 through 1.4 are still maintained
- Bob finds the bug is present in 1.2.x but not 1.1.x
- Bob checks out the 'release-1.2' branch
- Bob develops, tests, and commits a fix
- Bob checks out 'release-1.3', merges with 'release-1.2', tests, and commits
- Bob checks out 'release-1.4', merges with 'release-1.3', tests, and commits
- Bob checks out 'default', merges with 'release-1.3', tests, and commits
It is not necessary to merge after every fix, but merging regularly will reduce the number of merge conflicts and keep your branches more current. When forward-porting, most merges should be automatic.
5.3. Backporting fixes
Do not try merging the default branch into a release branch to backport a bugfix as it will also merge in all new features!
Occasionally, fixes are committed on the development branch before issues are discovered on the release branches. In this case, you'll need to first 'backport' your change:
$ hg export 23485 > fix.patch $ hg up release-1.1 44 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg import fix.patch applying fix.patch
Backporting a patch is generally not as easy as forward-porting, due to the likelihood of new fixes being dependent on new features. Thus, you may need to handle some patch rejects when backporting.
Now you'll have a duplicate fix on your release-1.1 branch and you can forward-port it to your other release branches as before.
The TransplantExtension can help automate this process.