6978
Comment:
|
← Revision 18 as of 2014-06-25 21:38:29 ⇥
7269
replace link to graft with a better one
|
Deletions are marked like this. | Additions are marked like this. |
Line 2: | Line 2: |
Line 4: | Line 3: |
Line 10: | Line 8: |
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: |
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: |
Line 16: | Line 12: |
* release branches are regularly merged 'upward' to propagate fixes | * release branches are regularly merged 'forward' in time to propagate fixes |
Line 19: | Line 15: |
Line 22: | Line 17: |
=== Don't use a name other than default for your main development branch === Mercurial's main branch is called "default" and is analogous to "trunk" in SVN, "HEAD" in CVS, and "master" in Git. It is the branch that is checked out by new clones. If you try to use some other name for your "main" branch, users will get a more or less random branch when they clone and commit things in the wrong place, which is generally undesirable. |
=== Don't use a name other than default for your main development branch === Mercurial's main branch is called "default" and is analogous to "trunk" in SVN, "HEAD" in CVS, and "master" in Git. If you try to use some other name for your "main" branch, users will get a more or less random branch when they clone and commit things in the wrong place, which is generally undesirable. |
Line 28: | Line 21: |
If you're coming from Git, you may be used to the idea that branch names are disposable. Mercurial's model is more traditional: branch names are a permanent part of each commit and allow identifying on which branch each commit was introduced. Thus you will want to give some thought to your branch names so that you don't pollute the branch namespace. | |
Line 29: | Line 23: |
If you're coming from Git, you may be used to the idea that branch names are disposable. Mercurial's model is more traditional: branch names are a permanent part of each commit and allow identifying on which branch each commit was introduced. Thus you will want to give some thought to your branch names so that you don't pollute the branch namespace. Also, if you attempt to use a branch per bugfix, you may eventually run into performance issues. Mercurial is designed to work well with hundreds of branches; tests with tens of thousands of branches however show noticeable overhead. |
Also, if you attempt to use a branch per bugfix, you may eventually run into performance issues. Mercurial is designed to work well with hundreds of branches. It still works quite well with ten thousand branches, but some commands might show noticeable overhead which you will only see after your workflow already stabilized. |
Line 34: | Line 26: |
Line 38: | Line 29: |
Line 44: | Line 34: |
Line 48: | Line 37: |
Line 56: | Line 44: |
Line 67: | Line 54: |
Line 69: | Line 55: |
Line 77: | Line 62: |
Line 79: | Line 63: |
Line 83: | Line 66: |
Line 85: | Line 67: |
Line 89: | Line 70: |
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'. |
After one or more fixes have been applied to a release branch, you should regularly merge that branch 'forward' in time into either the next more recent release branch or the development 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'. |
Line 115: | Line 94: |
Line 118: | Line 96: |
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: | 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. To do that use the Cmd:graft command that will utilize the merge machinery and your normal merge tool in case of conflicts. A more keep-it-simple and error prone approach is to use patches: |
Line 127: | Line 107: |
Line 132: | Line 111: |
<!> The TransplantExtension can help automate this process. | The TransplantExtension automates this process and makes it similar to Cmd:graft while using patches instead of merging. |
Line 135: | Line 114: |
Line 141: | Line 119: |
CategoryAudit | CategoryHowTo |
Standard Branching
How the Mercurial project itself manages branched development
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 'forward' in time to propagate fixes
2. What not to do
Some common mistakes for people coming from other systems:
2.1. Don't use a name other than default for your main development branch
Mercurial's main branch is called "default" and is analogous to "trunk" in SVN, "HEAD" in CVS, and "master" in Git. If you try to use some other name for your "main" branch, users will get a more or less random branch when they clone and commit things in the wrong place, which is generally undesirable.
2.2. Don't treat branch names as disposable
If you're coming from Git, you may be used to the idea that branch names are disposable. Mercurial's model is more traditional: branch names are a permanent part of each commit and allow identifying on which branch each commit was introduced. Thus you will want to give some thought to your branch names so that you don't pollute the branch namespace.
Also, if you attempt to use a branch per bugfix, you may eventually run into performance issues. Mercurial is designed to work well with hundreds of branches. It still works quite well with ten thousand branches, but some commands might show noticeable overhead which you will only see after your workflow already stabilized.
2.3. Don't use branch names that are the same as your tag names
If you have a branch named "1.0" and a tag named "1.0", you'll get surprising results when you try to check out "1.0". Pick a naming scheme for your branches that distinguishes them, eg "1.x", "1.0-dev", etc.
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 'forward' in time into either the next more recent release branch or the development 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.4', 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. To do that use the graft command that will utilize the merge machinery and your normal merge tool in case of conflicts.
A more keep-it-simple and error prone approach is to use patches:
$ 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 automates this process and makes it similar to graft while using patches instead of merging.