This is the final 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, the second part explains how to control them. This one explains what people should take care of when upgrading.

Important upgrade note and backward compatibility

Phases do not require any conversion of your repos. Phase information is not stored in changesets. Everybody using a new client will take advantage of phases on any repository they touch.

However there is some points you need to be aware of regarding interaction between the old world without phases and the new world with phases:

Talking over the wire to a phaseless server using a phased client

As ever, the Mercurial wire protocol (used to communicate through http and ssh) is fully backward compatible [1]. But as old Mercurial versions are not aware of phases, old servers will always be treated as publishing.

Direct file system access to a phaseless repository using a phased client

A new client has no way to determine which parts of the history should be immutable and which parts should not. In order to fail safely, a new repo will mark everything as public when no data is available. For example, in the scenario described in part I, if an old version of mercurial were used to clone and commit, a new version of mercurial will see them as public and refuse to rebase them.

Note

Some extensions (like mq) may provide smarter logic to set some changesets to the draft or even secret phases.

The phased client will write phase data to the old repo on its first write operation.

Direct file system access to a phased repository using a phaseless client

Everything works fine except that the old client is unable to see or manipulate phases:

  • Changesets added to the repo inherit the phase of their parents, whatever the parents' phase. This could result in new commits being seen as public or pulled content seen as draft or even secret when a newer client uses the repo again!
  • Changesets pushed to a publishing server won't be set public.
  • Secret changesets are exchanged.
  • Old clients are willing to rewrite immutable changesets (as they don't know that they shouldn't).

So, if you actively rewrite your history or use secret changesets, you should ensure that only new clients touch those repositories where the phase matters.

Fixing phases error

Several situations can result in bad phases in a repository:

  • When upgrading from phaseless to phased Mercurial, the default phases picked may be too restrictive.
  • When you let an old client touch your repository.
  • When you push to a publishing server that should not actually be publishing.

The easiest way to restore a consistant state is to use the phase command. In most cases, changesets marked as public but absent from your real public server should be moved to draft:

hg phase --force --draft 'public() and outgoing()'

If you have multiple public servers, you can pull from the others to retrieve their phase data too.

Conclusion

Mercurial's phases are a simple concept that adds always on and transparent safety for most users while not preventing advanced ones from doing whatever they want.

Behind this safety-enabling and useful feature, phases introduce in Mercurial code the concept of sharing mutable parts of history. The introduction of this feature paves the way for advanced history rewriting solutions while allowing safe and easy sharing of mutable parts of history. I'll post about those future features shortly.


[1]You can expect the 0.9.0 version of Mercurial to interoperate cleanly with one released 5 years later.

[Images by Crystian Cruz (cc-nd) and C.J. Peters (cc-by-sa)]

blog entry of

Logilab.org - en