This is the second part of a series of posts about the new phases feature we implemented for mercurial 2.1. The first part talks about how phases will help mercurial users, this second part explains how to control them.

Controlling automatic phase movement

Sometimes it may be desirable to push and pull changesets in the draft phase to share unfinished work. Below are some cases:

  • pushing to continuous integration,
  • pushing changesets for review,
  • user has multiple machines,
  • branch clone.

You can disable publishing behavior in a repository configuration file [1]:

[phases]
   publish=False
   

When a repository is set to non-publishing, people push changesets without altering their phase. draft changesets are pushed as draft and public changesets are pushed as public:

celeste@Chessy ~/palace $ hg showconfig phases
   phases.publish=False
   
babar@Chessy ~/palace $ hg log --graph
   @  [draft] add a carpet (2afbcfd2af83)
   |
   o  [public] Add a table in the kichen (139ead8a540f)
   |
   o  [public] Add wall color (0d1feb1bca54)
   |
   
   babar@Chessy ~/palace $ hg outgoing ~celeste/palace/
   [public] Add wall color (0d1feb1bca54)
   [public] Add a table in the kichen (139ead8a540f)
   [draft] add a carpet (3c1b19d5d3f5)
   babar@Chessy ~/palace $ hg push ~celeste/palace/
   pushing to ~celeste/palace/
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 3 changesets with 3 changes to 2 files
   babar@Chessy ~/palace $ hg log --graph
   @  [draft] add a carpet (2afbcfd2af83)
   |
   o  [public] Add a table in the kichen (139ead8a540f)
   |
   o  [public] Add wall color (0d1feb1bca54)
   |
   
   
celeste@Chessy ~/palace $ hg log --graph
   o  [draft] add a carpet (2afbcfd2af83)
   |
   o  [public] Add a table in the kichen (139ead8a540f)
   |
   o  [public] Add wall color (0d1feb1bca54)
   |
   
   

And pulling gives the phase as in the remote repository:

celeste@Chessy ~/palace $ hg up 139ead8a540f
   celeste@Chessy ~/palace $ echo The wall will be decorated with portraits >> bedroom
   celeste@Chessy ~/palace $ hg ci -m 'Decorate the wall.'
   created new head
   celeste@Chessy ~/palace $ hg log --graph
   @  [draft] Decorate the wall. (3389164e92a1)
   |
   | o  [draft] add a carpet (3c1b19d5d3f5)
   |/
   o  [public] Add a table in the kichen (139ead8a540f)
   |
   o  [public] Add wall color (0d1feb1bca54)
   |
   
   ---
   babar@Chessy ~/palace $ hg pull ~celeste/palace/
   pulling from ~celeste/palace/
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
   babar@Chessy ~/palace $ hg log --graph
   @  [draft] Decorate the wall. (3389164e92a1)
   |
   | o  [draft] add a carpet (3c1b19d5d3f5)
   |/
   o  [public] Add a table in the kichen (139ead8a540f)
   |
   o  [public] Add wall color (0d1feb1bca54)
   |
   
   

Phase information is exchanged during pull and push operations. When a changeset exists on both sides but within different phases, its phase is unified to the lowest [2] phase. For instance, if a changeset is draft locally but public remotely, it is set public:

celeste@Chessy ~/palace $ hg push -r 3389164e92a1
   pushing to http://hg.celesteville.com/palace
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
   celeste@Chessy ~/palace $ hg log --graph
   @  [public] Decorate the wall. (3389164e92a1)
   |
   | o  [draft] add a carpet (3c1b19d5d3f5)
   |/
   o  [public] Add a table in the kichen (139ead8a540f)
   |
   o  [public] Add wall color (0d1feb1bca54)
   |
   
   ---
   babar@Chessy ~/palace $ hg pull ~celeste/palace/
   pulling from ~celeste/palace/
   searching for changes
   no changes found
   babar@Chessy ~/palace $ hg log --graph
   @  [public] Decorate the wall. (3389164e92a1)
   |
   | o  [draft] add a carpet (3c1b19d5d3f5)
   |/
   o  [public] Add a table in the kichen (139ead8a540f)
   |
   o  [public] Add wall color (0d1feb1bca54)
   |
   
   

Note

pull is read-only operation and does not alter phases in remote repositories.

You can also control the phase in which a new changeset is committed. If you don't want new changesets to be pushed without explicit consent, update your configuration with:

[phases]
   new-commit=secret
   

You will need to use manual phase movement before you can push them. See the next section for details:

Note

With what have been done so far for 2.1, the "most practical way to make a new commit secret" is to use:

   hg commit --config phases.new-commit=secret
   
[1]You can use this setting in your user hgrc too.
[2]Phases as ordered as follow: public < draft < secret

Manual phase movement

Most phase movements should be automatic and transparent. However it is still possible to move phase manually using the hg phase command:

babar@Chessy ~/palace $ hg log --graph
   @    [draft] merge with Celeste works (f728ef4eba9f)
   |\
   o |  [draft] add a carpet (3c1b19d5d3f5)
   | |
   | o  [public] Decorate the wall. (3389164e92a1)
   |/
   o  [public] Add a table in the kichen (139ead8a540f)
   |
   
   babar@Chessy ~/palace $ hg phase --public 3c1b19d5d3f5
   babar@Chessy ~/palace $ hg log --graph
   @    [draft] merge with Celeste works (f728ef4eba9f)
   |\
   o |  [public] add a carpet (3c1b19d5d3f5)
   | |
   | o  [public] Decorate the wall. (3389164e92a1)
   |/
   o  [public] Add a table in the kichen (139ead8a540f)
   |
   
   

Changesets only move to lower [#] phases during normal operation. By default, the phase command enforces this rule:

babar@Chessy ~/palace $ hg phase --draft 3c1b19d5d3f5
   no phases changed
   babar@Chessy ~/palace $ hg log --graph
   @    [draft] merge with Celeste works (f728ef4eba9f)
   |\
   o |  [public] add a carpet (3c1b19d5d3f5)
   | |
   | o  [public] Decorate the wall. (3389164e92a1)
   |/
   o  [public] Add a table in the kichen (139ead8a540f)
   |
   
   

If you are confident in what your are doing you can still use the --force switch to override this behavior:

Warning

Phases are designed to avoid forcing people to use hg phase --force. If you need to use --force on a regular basis, you are probably doing something wrong. Read the previous section again to see how to configure your environment for automatic phase movement suitable to your needs.

babar@Chessy ~/palace $ hg phase --verbose --force --draft 3c1b19d5d3f5
   phase change for 1 changesets
   babar@Chessy ~/palace $ hg log --graph
   @    [draft] merge with Celeste works (f728ef4eba9f)
   |\
   o |  [draft] add a carpet (3c1b19d5d3f5)
   | |
   | o  [public] Decorate the wall. (3389164e92a1)
   |/
   o  [public] Add a table in the kichen (139ead8a540f)
   |
   
   

Note that a phase defines a consistent set of revisions in your history graph. This means that to have a public (immutable) changeset all its ancestors need to be immutable too. Once you have a secret (not exchanged) changeset, all its descendant will be secret too.

This means that changing the phase of a changeset may result in phase movement for other changesets:

babar@Chessy ~/palace $ hg phase -v --public f728ef4eba9f # merge with Celeste works
   phase change for 2 changesets
   babar@Chessy ~/palace $ hg log --graph
   @    [public] merge with Celeste works (f728ef4eba9f)
   |\
   o |  [public] add a carpet (3c1b19d5d3f5)
   | |
   | o  [public] Decorate the wall. (3389164e92a1)
   |/
   o  [public] Add a table in the kichen (139ead8a540f)
   |
   
   babar@Chessy ~/palace $ hg phase -vf --draft 3c1b19d5d3f5 # add a carpet
   phase change for 2 changesets
   babar@Chessy ~/palace $ hg log --graph
   @    [draft] merge with Celeste works (f728ef4eba9f)
   |\
   o |  [draft] add a carpet (3c1b19d5d3f5)
   | |
   | o  [public] Decorate the wall. (3389164e92a1)
   |/
   o  [public] Add a table in the kichen (139ead8a540f)
   |
   
   

The next and final post will explain how older mercurial versions interact with newer versions that support phases.

[Images by Jimmy Smith (cc-by-nd) and Cory Doctorow (cc-by-sa)]

blog entry of

Logilab.org - en