Wiki
hgflow / Home
Welcome to hgflow wiki!
Here we document hgflow -- a Mercurial extension that implements a generalized Driessen branching model.
What's New
v0.9.8.x
- Bug fixes. Most of the fixes are for compatibility with the latest version of Mercurial.
v0.9.8
- Added
rename
action to enable user to rename a branch which has not yet been merged. - Better handling of multihead branches
- A number of bug fixes
v0.9.7
- Removed dependency on the
ConfigParser
module. This is a good news for Windows users. - Smarter error messages. If you make typos in your command, hgflow can now suggest corrections. For example:
> hg flow hotfis
flow: error: Stream not found: <hotfis>
flow: note: Did you mean: hotfix?
> hg flow hotfix stat 0.9.7.1
flow: error: Invalid action or unknown branch in <hotfix>: 'stat'
flow: note: Did you mean: start?
> hg flow hotfix close
flow: error: Invalid action or unknown branch in <hotfix>: 'close'
flow: note: Did you mean: finish or abort?
- Minor enhancements and bug fixes
v0.9.6
- Many minor enhancements and bug fixes
- Performance improvement
- Added
-d --default
option for theinit
command. This feature allows automation of initialization of hgflow. For example, you can automatically initialize hgflow when you initialize hg by adding the following setting in your hg's configuration file:
...
[hooks]
post-init.flow = hg flow init -d
- Added
--stamp
option for all actions or commands that can commit changes. What this option does is to append a user-specified string (such as an issue key) in all commit messages of this hg-flow command. For example:
$ hg flow feature finish --stamp "Issue-20" --dry-run --verbose
flow: This is a dry run.
flow: note: Hg command history:
flow: note: hg commit --message "flow: Closed <feature> 'b'. Issue-20" --close-branch
flow: note: hg update develop
flow: note: hg merge feature/b
flow: note: hg commit --message "flow: Merged <feature> 'b' to <develop> ('develop'). Issue-20"
- Added
version_prefix
configuration keyword to allow user to customize the version prefix. By default, this prefix is 'v'. Usage example: In hg's configuration file:$HOME/.hgrc
(or%USERPROFILE%/Mercurial.ini
on Windows):
...
[flow]
autoshelve = yes
version_prefix = ver
v0.9.5
- Added
--user
forinit
,start
,finish
, andpromote
actions. --closed
is now an option of thelog
action. This option letslog
show the revision history of both open and closed branches in the specified stream.- Added
--dirty
for thestart
action. This option enables user to start a new branch from a dirty working directory and move all the uncommitted changes to the new branch. - Added
--erase
for thefinish
action. With this option, you erase (i.e., completely delete from the repository) the branch after it is successfully finished. The final effect is as if all changes in the branch were collapsed and then committed as a single changeset to the destination branch which the branch was merged to. Check outhg flow help @finish
for a bit more detail. - Added
--erase
for theabort
action. This option enables you to erase (i.e., completely delete from the repository) the entire branch when you abort it. Check outhg flow help @abort
for a bit more detail. - Now you can promote a
<develop>
branch directly to<master>
, bypassing<release>
. This feature provides a shortcut from the<develop>
directly to<master>
. I found it very useful especially for small projects, where you don't really need a "release" (or QA) stage and you want continuous deployment of newly developed features. Such a workflow can be considered as a simplified/reduced version of the Driessen's model and was promoted by some people (e.g., github, and they call it github flow). Example usage:
$ # Ensures the working directory is the <develop> branch that we want to release.
$ hg flow develop
# Now we release. With the '-t' option, you can supply a tag for the released snapshot in the <master> branch. The command takes the '--dry-run' option in order to show what exactly happens.
$ hg flow develop promote -t "v0.9.5" --dry-run
flow: This is a dry run.
flow: note: Hg command history:
flow: note: hg update default
flow: note: hg merge develop
flow: note: hg commit --message "flow: Promoted <develop> 'trunk' (abdae6de9735) to 'default'."
flow: note: hg tag v0.9.5
flow: note: hg update develop
v0.9.4
- Add support for generalized streams.
- Add an advanced help system.
- Add support for colorized messages.
- Add
promote
action. - Add
abort
action. - Add
upgrade
command. - Add
--dry-run
option. - Add a number of command/action's options.
- Allow users to customize commit message prefix.
v0.8.x
The latest version in the 0.8 release line is v0.8.3.
- Add
rebase
action that can rebase a branch to its parent branch. - Add
log
action for all streams. - Add
unshelve
command. - Add
version
command. - Support autoshelve -- automatically shelve uncommitted changes before you switch to another branch and automatically unshelve the changes when you switch back to the previous branch.
- The
list
action is able to indicates which ones have shelved changes. - Show latest tag of the master stream.
- A lot more friendly and capable
hg flow-init
command - Support the
--history
option forhg flow-init
command. - Honor the
--trackback
option.
v0.7.x
The latest version in the 0.7 release line is v0.7.2.
- Support
start
,finish
,push
,publish
,pull
, andlist
actions for the feature, release, hotfix, and support streams. - Support
push
,publish
, andpull
actions for the develop and master streams. - Easy switch to a branch.
- Shortcut command to list all branches in a stream.
- Support listing all branches in all streams.
- Support --history option to record the hg commands used by this hgflow command.
History
Version 0.3 and earlier versions of hgflow was written by yinwm.
On July 14 2011, I forked the version 0.3. My goals were (1) to provide superior Mercurial support for Driessen's branching model and (2) to implement a few ideas that generalize and enhance this model. I completely rewrote the code to get a cleaner code base that I could further work on. This work resulted in version 0.7, which also provided a more complete set of commands than 0.3, and IMO it's even better than gitflow.
I then implemented several important enhancements on usability, such as autoshelve, --history
option, rebase
and log
actions. These made hgflow a lot nicer to use. This work was published as version 0.8.x.
Aftewards, the code was again deeply refactored to support generalized streams. In addition, an advanced help system, an infrastructure for parsing subcommand options, and a mechanism for colorizable messages were established. These made hgflow more powerful and friendly, and made it easier for further enhancements. A number of useful options, including --dry-run
and --onstream
, were implemented.
Introduction
In software engineering, branching is diverging the development so that the source code can evolve parallelly on independent tracks. Branching will result in multiple normally complementary versions of source code -- branches. Branches eventually will be merged to yield a more mature version that incorporates all necessary features/fixes as individually developed in branches. Branching and merging, if used wisely, will make software development process less messy and more controllable, especially in distributed scenarios.
How to systematically branch and merge source code is a common problem facing software engineers in using version control system. Among other successful models, the one proposed by Vincent Driessen is particularly attractive to us. If you haven't, we encourage you to read the original article.
In short, Driessen's model distinguishes 6 types of branches in the purpose of code, namely, master, develop, feature, release, hotfix, and support. Any branch is of one of these types. We can call the entire set of branches of the same type as a stream. So there are 6 streams: (again) master, develop, feature, release, hotfix, and support. They evolve as its member branches emerge, change, and terminate. In general, a stream can contain 0 or more branches and the number can change along time. The master and develop streams are, however, a bit special in that they contain 1 only 1 branch for all the time. From our understanding, stream is a fundamental concept in Driessen's model. Operations on branches can be redefined in terms of stream, giving us high-level commands that make our life time a bit easier.
Hgflow is a Mercurial extension that implements Driessen's model. It supplies users high
level stream-based commands for managing branches. The original implementation was inspired
by git-flow - an earlier implementation for the git
version control system. Many commands and usages in hgflow are similar to git-flow. Experience
learned in using gitflow can be directly transferred to hgflow. An excellent introduction
to usage of git-flow can be found at here.
Generalized Driessen's Branching Model
Stream in its bare essence is a set of branches. Removing some restrictions in the original concept, we generalize stream to refer to any set of branches. This simple generalization results in a more powerful and flexible model.
There is one particularly useful type of streams. Say we have a branch called
trunk. We can open new branches from the trunk, and later we can merge the
branches back to it. This is in fact a common branching and merging
pattern. All branches from the same trunk plus the trunk itself natually form
a stream, and we call it natural stream
. We don't have to do something
special to create a natural stream, which becomes existent as long as the trunk is.
In contrast, the master, develop, feature, release, hotfix, and
support are preexisting streams, and they are sortof artificial. Hgflow has been
enhanced to support natural streams since v0.9. Let's see how it can be used.
Say we want a branch called A in the feature stream. We can start it using the following command:
$ hg flow develop
$ hg flow feature start A
Now we have a branch: <feature-prefix>/A. Since we can consider any branch as a trunk from which we open other branches, a natural stream is spontaneously created whenever a new branch is created. In the example here, we have a natural stream: feature/A.
$ hg flow feature/A
$ # Switch to the trunk of <feature/A>.
$ # This command is largely equivalent to the more familiar command:
$ # hg flow feature A
$ hg flow feature/A start a1
$ # Start a new branch in <feature/A>. The new branch is named after <feature-prefix>/A/a1.
$ hg flow feature/A a1
$ hg flow feature/A finish
$ # Finish the <feature-prefix>/A/a1 branch.
$ # Merge it to the trunk of <feature/A>, and close it.
You can call <feature/A> as a substream of <feature>. Branches in <feature/A> are, of course, also in <feature>. So you can operate branches in <feature/A> at the level of <feature>. For example, you can finish the <feature-prefix>/A/a1 branch as a regular branch in <feature>.
$ hg flow feature/A a1
$ hg flow feature finish
$ # Finish the <feature-prefix>/A/a1 branch.
$ # Merge it to <develop>, and close it.
$ # Note how the effect differs from that of the prior command: hg flow feature/A finish.
Branches in Develop Stream
We allow users to start branches in the develop stream. Each branch in <develop> is a substream in <develop>. You can use this substream to start new branches in <release> and/or <feature>. Examples.
$ hg flow develop
$ # Update workspace to <develop>'s trunk.
$ hg flow develop start spring
$ # Start a new branch called <develop-prefix>/spring.
$ hg flow develop/spring:feature start feature_for_spring_release
$ # Start a new branch called <feature-prefix>/feature_for_spring_release.
$ # This branch is started from <develop/spring> instead of <develop>.
$ # Note the syntax for specifying the stream: <source-stream>:<stream>, which is
$ # available since v0.9 and means that the action will operate on a branch in <stream>,
$ # but the source (or destination) stream is not the default, but specified by <source-stream>.
$ # This is a more general syntax. You can consider the familiar command:
$ # hg flow feature start <name>
$ # as a shorthand of this command:
$ # hg flow develop:feature start <name>
$ hg flow develop/spring:feature finish
$ # Finish a <feature> branch. Merge the branch to the trunk of <develop/sprint>, instead of <develop>.
One special thing about <develop> substreams is that when a feature branch is being finished and merged into a <develop> substream, the trunk of the substream will be automatically merged into the <develop> trunk as part of the workflow. For example:
$ hg flow develop/spring:feature finish --dry-run
flow: This is a dry run.
flow: note: Hg command history:
flow: note: hg commit --message "flow: Closed <feature> 'new_spring_feature'." --close-branch
flow: note: hg update develop/spring
flow: note: hg merge feature/new_spring_feature
flow: note: hg commit --message "flow: Merged <feature> 'new_spring_feature' to <develop/spring> ('develop/spring')."
flow: note: hg update develop
flow: note: hg merge develop/spring
flow: note: hg commit --message "flow: Merged <develop/spring:feature> 'new_spring_feature' to <develop> ('develop')."
The effects are similar for finishing a <release> branch. For example:
$ hg flow develop/spring:release finish --dry-run
flow: This is a dry run.
flow: note: Hg command history:
flow: note: hg commit --message "flow: Closed <release> '2012_spring_release'." --close-branch
flow: note: hg update develop/spring
flow: note: hg merge release/2012_spring_release
flow: note: hg commit --message "flow: Merged <release> '2012_spring_release' to <develop/spring> ('develop/spring')."
flow: note: hg update develop
flow: note: hg merge develop/spring
flow: note: hg commit --message "flow: Merged <develop/spring:release> '2012_spring_release' to <develop> ('develop')."
flow: note: hg update default
flow: note: hg merge release/2012_spring_release
flow: note: hg commit --message "flow: Merged <release> '2012_spring_release' to <master> ('default')."
flow: note: hg tag v2012_spring_release
Another special thing of <develop> branches is that when you finish a branch in <develop> stream (not in a develop substream though), a new <release> branch will be created. For example:
$ hg flow develop spring
$ # Update workspace to <develop-prefix>/spring branch.
$ hg flow develop finish --dry-run
flow: This is a dry run.
flow: note: Hg command history:
flow: note: hg update develop/spring
flow: note: hg branch release/spring
flow: note: hg commit --message "flow: Created branch 'release/spring'."
flow: note: hg update develop/spring
flow: note: hg commit --message "flow: Closed <develop> 'spring'." --close-branch
flow: note: hg update develop
flow: note: hg merge develop/spring
flow: note: hg commit --message "flow: Merged <develop> 'spring' to <develop> ('develop')."
flow: note: hg update release/spring
Act on a Stream
Several actions can act on a stream with the --onstream option: finish, rebase, log, and abort.
In other words, they act on each branch in the stream.
License
GPL 2.0.
Installation
0. Requirements: You need hg
version 1.6 or later. Some features, for example,
autoshelve and rebase, need the
mq and
rebase extensions.
1. To get hgflow, you can either clone the repository, or download the latest version from here.
2. Unpack and copy the hgflow.py
file to an arbitrary directory, e.g., $HOME/.hgext/
.
3. Edit hg configuration file: $HOME/.hgrc
(or %USERPROFILE%/Mercurial.ini
on Windows; refer to here if you are unsure which file to edit.). Add the following lines:
[extensions]
flow = /PATH/TO/hgflow.py
4. (optional) If you use a pager, you might want to let it ignore hgflow, since it could hide hgflow's input prompts.
For example, I have the following lines in my $HOME/.hgrc
file to let the pager ignore hg flow init
command (among others):
[pager]
pager = LESS='FSRX' less
ignore = version, help, update, flow init
Initialization and Configuration
You have to initialize hgflow for every repository where you want to use hgflow.
$ cd <my_repository_dir>
$ hg flow init
The flow init
command will create a configuration file: .hgflow
in
the root dir of the repository. Before doing so, it will ask you branch names or prefixes for each basic stream.
Type your preferred names or press return to use the default.
Branch name for master stream: [default] Branch name for develop stream: [develop] Branch name prefix for release stream: [release/] Branch name prefix for feature stream: [feature/] Branch name prefix for hotfix stream: [hotfix/] Branch name prefix for support stream: [support/]
Since the configuration file is tracked by hg
, if you have multiple existing branches, hgflow will
need to write the configuration file in each open branch. This will be done automatically by
hg flow init
command.
Autoshelve
Versions 0.8 and later provide a feature called autoshelve. It can automatically shelve uncommitted changes in the current workspace right before you switch to a different branch, and later when you switch back, it will automatically unshelve the changes. You can turn on this feature by adding the following lines in your hg configuration file:
[flow]
autoshelve = true
This feature needs the mq extension.
Commit Message Prefix
Versions 0.9.3 and later allow users to customize the commit-message prefix, which
by default is flow:
, thanks to Greg Salt for the initial
implementation. You can customize the prefix in your hg's configuration file, for example:
[flow]
prefix = "my_custom_prefix: "
You can remove the prefix entirely by setting prefix
to an empty string: ""
.
Upgrade to v0.9
Use hg flow upgrade
to make the change for your repository.
Commands
Basic syntax of hgflow commands:
$ hg flow {<stream> [<action> [<arg>...]] | <command>} [<option>...]
where <stream>
should be a (generalized) stream, which can be one of the basic streams:
master
, develop
, feature
, hotfix
, release
, and support
, or a natural stream, e.g., feature/log_options
.
Actions:
Action | Description |
---|---|
start | Open a new branch in the stream. |
finish | Close workspace branch and merge it to destination stream(s). |
push | Push workspace branch to the remote repository. |
publish | Same as push |
pull | Pull from the remote repository and update workspace branch. |
list | List all open branches in the stream. |
log | Show revision history of branch. |
promote | Merge workspace to other branches. (not closing any branches.) |
rebase | Rebase workspace branch to its parent branch. |
abort | Abort branch. Close branch without merging. |
Commands:
Command | Description |
---|---|
init | Initialize flow. |
unshelve | Unshelve the previously shelved changes for workspace branch. |
upgrade | Upgrade the configuration file to v0.9.5 or later. |
help | Show help for a specific topic. Example: hg flow help @help |
version | Show flow's version number. |
Options:
Option | Description | Actions/Commands |
---|---|---|
--history | Print history of hg commands used in this workflow. | all |
--dry-run | Do not perform actions, only print history. | all |
--dirty | Start a new branch from a dirty workspace, and move all uncommitted changes to the new branch. | start |
--traceback | Print trace back when hgflow command fails. | all |
--verbose | Call hg commands with the --verbose option, and print history of hg commands used in this workflow. | all |
-c --closed | Show normal and closed branches in stream. | list, log |
-c --commit | Commit changes before closing the branch. | finish |
-d --default | Initialize flow with default configuration. | init |
-d --date DATE | Record the specified date as commit date. | start, finish, promote |
-d --date DATE | Show revisions matching date spec. | log |
-d --dest REV | Destination changeset of rebasing. | rebase |
-e --erase | Erase branch after it is merged or aborted successfully. | finish, abort |
-F --file FILE [+] | File to show history of. | log |
-f --force | Force reinitializing flow. | init |
-g --git | Use git extended diff format to show patch. | log |
-k --keyword TEXT | Do case-insensitive search for a given text. | log |
-l --limit VALUE | Limit number of changesets displayed. | log |
-m --message TEXT | Record TEXT as commit message. | start, finish, promote, abort |
-p --stamp TEXT | Append TEXT to all commit messages. | init, upgrade start, finish promote, rebase abort |
-p --patch | Show patch. | log |
-r --rev REV | Revision to start a new branch from. | start |
-r --rev REV | Revision to promote to other branches. | promote |
-s --onstream | Act on stream. | finish, rebase, log, abort |
-t --tag NAME | Tag the merging changeset with NAME. | promote |
-t --tag NAME | Tag the <master> trunk with NAME after merging. | finish |
-u --user USER | Use specified user as committer. | init, start, finish, promote |
-u --user USER | Show revisions committed by specified user. | log |
Updated