mutable-history / docs / obs-terms.rst

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 precursors while their new versions are called successors. A marker always registers a single precursor and:

  • no successor: the precursor is just discarded.
  • one successor: the precursor has been rewritten
  • multiple successors: the precursor 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 precursors 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 precursors:are transitive precursors of a changeset: direct precursors and precursors of precursors.
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 precursors of a changeset may be unknown locally. This is why we usually focus on the first known precursors 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 precursor.

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


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

Thoses descendants prevent properties of extincts changesets to apply. But they will refuse to be pushed without --force.


troubled has unresolved issue caused by obsolete relations.

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

(possible alternative names: unsettled, troublesome


unstable is a changeset with obsolete ancestors.

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

(possible alternative name: precarious)


bumped is a changeset that tries to be successor of public changesets.

Public changeset can't be deleted and replace bumped need to be converted into an overlay to this public changeset.

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


divergent is changeset that appears when multiple changesets are successors of the same precursor.

divergent are solved through a three ways merge between the two divergent , using the last "obsolete- -common-ancestor" as the base.

(splitting is properly not detected as a conflict)

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

Mutable changesets which are neither obsolete or troubled 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 precursors have no effect on the precussors 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 (unstable, bumped and 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
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
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.