evolve extension for Mercurial

Terminology of the obsolete concept

«  Good practice for (early) users of evolve   ::   Contents   ::   Topic Tutorial  »

Terminology of the obsolete concept

Obsolete markers

The mutable concept is based on obsolete markers. Creating an obsolete marker registers a relation between an old obsoleted changeset and its newer version.

Old changesets are called predecessors while their new versions are called successors. A marker always registers a single predecessor and:

  • no successor: the predecessor is just discarded.
  • one successor: the predecessor has been rewritten
  • multiple successors: the predecessor were splits in multiple changesets.

Chaining obsolete markers is allowed to rewrite a changeset that is already a successor. This is a kind of second order version control. To clarify ambiguous situations one can use direct predecessors or direct successors to name changesets that are directly related.

The set of all obsolete markers forms a direct acyclic graph the same way standard parents/children relation does. In this graph we have:

any predecessors:
 are transitive predecessors of a changeset: direct predecessors and predecessors of predecessors.
any successors:are transitive successors of a changeset: direct successors and successors of successors)

Obsolete markers may refer changesets that are not known locally. So, direct predecessors of a changeset may be unknown locally. This is why we usually focus on the first known predecessors of the rewritten changeset. The same apply for successors.

Changeset in any successors which are not obsolete are called newest successors..


I’m not very happy with this naming scheme and I’m looking for a better distinction between direct successors and any successors.

Possible changesets “type”

The following table describes names and behaviors of changesets affected by obsolete markers. The left column describes generic categories and the right columns are about sub-categories.


Changeset in either draft or secret phase.


Obsolete changeset is mutable used as a predecessor.

A changeset is used as a predecessor when at least one obsolete marker refers to it as predecessors.


extinct changeset is obsolete which has only obsolete descendants.

They can safely be:

  • hidden in the UI,
  • silently excluded from pull and push operations
  • mostly ignored
  • garbage collected


suspended changeset is obsolete with at least one non-obsolete descendant

Those descendants prevent properties of extinct changesets to apply. But they will refuse to be pushed without –force.


unstable has unresolved issue caused by obsolete relations.

Possible issues are listed in the next column. It is possible for unstable changeset to combine multiple issue at once. (a.k.a. content-divergent and orphan)

(possible alternative names: unsettled, troublesome


orphan is a changeset with obsolete ancestors.

It must be rebased on a non unstable base to solve the problem.

(possible alternative name: precarious)


phase-divergent is a changeset that tries to be successor of a public changeset.

Public changeset can’t be deleted and replace phase-divergent need to be converted into an overlay to this public changeset.

(possible alternative names: mislead, naive, unaware, mindless, disenchanting)


content-divergent is a changeset that appears when multiple changesets are successors of the same predecessor.

content-divergent are solved through a three way merge between the two content-divergent , using the last “obsolete- -common-ancestor” as the base.

(splitting is properly not detected as a conflict)

(possible alternative names: clashing, rival, concurrent, conflicting)

Mutable changesets which are neither obsolete or unstable are “ok”.

Do we really need a name for it ? “ok” is a pretty crappy name :-/ other possibilities are:

  • stable (confusing with stable branch)
  • sane
  • healthy

Changesets in the public phases.

Rewriting operation refuse to work on immutable changeset.

Obsolete markers that refer an immutable changeset as predecessors have no effect on the predecessors but may have effect on the successors.

When a mutable changeset becomes immutable (changing its phase from draft to public) it is just immutable and loose any property of it’s former state.

The phase properties says that public changesets stay as immutable forever.

Command and operation name

Existing terms

Mercurial core already uses the following terms:

amend:to rewrite a changeset
graft:to copy a changeset
rebase:to move a changeset


Remove files from a commit (and leave them as dirty in the working directory)

The evolve extension have an uncommit command that aims to replace most rollback usage.


Collapse multiple changesets into a unique one.

The evolve extension will have a fold command.


Make a changeset obsolete without successors.

This an important operation as it should mostly replace strip.

Alternative names:

  • kill: shall has funny effects when you forget “hg” in front of hg kill.
  • obsolete: too vague, too long and too generic.


Automatically resolve troublesome changesets (orphan, phase-divergent and content-divergent)

This is an important name as hg pull/push will suggest it the same way it suggest merging when you add heads.

Alternative names:

  • solve (too generic ?)
  • stabilize

«  Good practice for (early) users of evolve   ::   Contents   ::   Topic Tutorial  »