Mercurial Phases Introduction

Alejandro Baez
4 min readJan 28, 2016

--

Mercurial’s history and introduction on phases.

Secret Garden by jenny downing

Mercurial has a lot of abilities hidden underneath. While the mercurial wiki can help introduce some of these abilities, it can be quite a daunting effort to find what you want through its documentation. So let’s see if a little write up on one of these features can unlock its secrets.

Phases were introduced a little while ago on mercurial, but for some reason, they remain a mystery to many. Heck, I didn’t even know of their existence until the deprecation debacle of Mercurial Queues. Yet, once you given the time to learn phases, it can be quite an excellent tool for ease in changeset management of your work. Enough so that it can give reason to not use Mercurial Queues, with the changeset evolution tools…

So what are phases? In the most naively simplistic definition of them, phases are the state of your changesets pushed upstream. In other words, they allow you to know which revisions were published and which are still in development on your repository. Phases do a great deal more than this, but let's keep the definition simple at first and expand it a few words after the introduction. The first two phases I'm defining grotesquely naively here are the draft (unpublished) and public (published) phase states of your changesets. Let’s do a simple example of these two states of phases to see the simplicity of their form.

Say I have a project I'm currently working on and it's brand spanking new from the initial commit. Since none of the changesets have yet to be published, meaning pushed to some host, all the changesets in the repository would default to draft. You can see this by running a quick log check of the phases in the repository with the following command:

hg phase 0:
first example: revisions [0:4] are all in draft phase.

Now lets take revisions 0 and 1 and actually push them to a host. These two changesets have now been published, and as such, are now in the public phase.

second example: revisions [0:1] published, making them public.

Simple enough, however there is so much more in play here. Phases true purpose is manageable mutability of your history stack on your repository. One of the reasons why people jump to git and look at everything else as foreign is due to the full accessed mutability of the changeset history. This mutability is so permissible on git, that you can even change published changesets with the oh so famous git push -force. Mercurial traditionally was immutable on all changesets’ type of production. Meaning it did not allow for mutability of the changesets, once you committed one. In shorthand, treating commits as immutable production changesets. This is why the hack rollback exists on mercurial.

Mercurial actually fought quite a while with how to tackle the challenge of mutable history. The end result became the phase states with changeset evolution. Now I’ll reintroduce the states and actually explain them hopefully in better detail. Your repository initially starts with the draft phase by default. Along with this, the phase state is derived from the parent changeset. It is why all the phases were draft on the above first example. The draft phase allows you to have pure mutability of your changeset. That is, you can rebase, strip, histedit, bisect, or do whatever else of the mutability capabilities you wish to do in mercurial.

The submissive mutability, like in git, is applicable until you publish your work to another host. Then the mutability becomes immutable with the phase raised to public. Once the phase becomes public for a changeset, it is in the immutable state. You cannot edit and change that changeset or any of the changeset preceding it for that matter. More so, once the state of an intermediary changeset is increased to public, the preceding parents to the changeset are all raised to public as well. This makes sense, consider the state is immutable on public. Thus, you do need the preceding changesets to be immutable as well for its permeability to be actually true.

third example: revisions [0:4] are all immutable due to public phase change of revision 4.

The combination of both the public phase and draft phase can transform how you use mercurial. Mercurial’s answer to re-writable history is the best both git and mercurial’s chain of the thought, in my opinion. It is a tool which you should definitely become comfortable using. You can work on rewriting the history of your changesets to the point you can make your mercurial workflow be as natural as you want it to be. With that said, I think this is enough of an introduction in what are phases. Instead, I’ll leave the more intricate details of how to use the phases on to another foreseeable published post. Maybe even explain why I think mercurial queues may not be needed with phases and speak a bit about the third secret (pun intended) state of the mercurial phases.

--

--

Alejandro Baez

Programming a program to program in Rust. Let’s see how that goes…