Wiki

Clone 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.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 the init 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 for init, start, finish, and promote actions.
  • --closed is now an option of the log action. This option lets log show the revision history of both open and closed branches in the specified stream.
  • Added --dirty for the start 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 the finish 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 out hg flow help @finish for a bit more detail.
  • Added --erase for the abort action. This option enables you to erase (i.e., completely delete from the repository) the entire branch when you abort it. Check out hg 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.

v0.7.x

The latest version in the 0.7 release line is v0.7.2.

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 the link: hgflow v0.9.5.
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:

ActionDescription
startOpen a new branch in the stream.
finishClose workspace branch and merge it to destination stream(s).
pushPush workspace branch to the remote repository.
publishSame as push
pullPull from the remote repository and update workspace branch.
listList all open branches in the stream.
logShow revision history of branch.
promoteMerge workspace to other branches. (not closing any branches.)
rebaseRebase workspace branch to its parent branch.
abortAbort branch. Close branch without merging.


Commands:

CommandDescription
initInitialize flow.
unshelveUnshelve the previously shelved changes for workspace branch.
upgradeUpgrade the configuration file to v0.9.5 or later.
helpShow help for a specific topic. Example: hg flow help @help
versionShow flow's version number.


Options:

OptionDescriptionActions/Commands
--historyPrint history of hg commands used in this workflow.all
--dry-runDo not perform actions, only print history.all
--dirtyStart a new branch from a dirty workspace, and move all uncommitted changes to the new branch.start
--tracebackPrint trace back when hgflow command fails.all
--verboseCall hg commands with the --verbose option, and
print history of hg commands used in this workflow.
all
-c --closedShow normal and closed branches in stream.list, log
-c --commitCommit changes before closing the branch.finish
-d --defaultInitialize flow with default configuration.init
-d --date DATERecord the specified date as commit date.start, finish,
promote
-d --date DATEShow revisions matching date spec.log
-d --dest REVDestination changeset of rebasing.rebase
-e --eraseErase branch after it is merged or aborted successfully.finish, abort
-F --file FILE [+]File to show history of.log
-f --forceForce reinitializing flow.init
-g --gitUse git extended diff format to show patch.log
-k --keyword TEXTDo case-insensitive search for a given text.log
-l --limit VALUELimit number of changesets displayed.log
-m --message TEXTRecord TEXT as commit message.start, finish,
promote, abort
-p --stamp TEXTAppend TEXT to all commit messages.init, upgrade
start, finish
promote, rebase
abort
-p --patchShow patch.log
-r --rev REVRevision to start a new branch from.start
-r --rev REVRevision to promote to other branches.promote
-s --onstreamAct on stream.finish, rebase,
log, abort
-t --tag NAMETag the merging changeset with NAME.promote
-t --tag NAMETag the <master> trunk with NAME after merging.finish
-u --user USERUse specified user as committer.init, start,
finish, promote
-u --user USERShow revisions committed by specified user.log





Developer Manual

Developer Manual (HTML format)

Updated

Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.