Note:

This page is primarily intended for developers of Mercurial.

Note:

This page is no longer relevant but is kept for historical purposes.

Liquid-HG

/!\ This feature have been implemented in Mercurial 2.1 as Phases

/!\ For general information about plan for history mutation in Mercurial, see MutableHG

A system for safely allowing mutable history.

Base concept

The first objective of Liquid-HG is to have a clear distinctions between the part of the history can be altered and the one which can't. (To keep it simple: the private part may be edited while the public can't). This imply two points

Other concepts

Garbage collection of "abandoned" changeset

For now, all extensions that alter history destroy old changeset by rewriting part of revlog. Most of them save a backout of the stripped part of the revlog in a bundle located at ".hg/strip-backup/"

Semantical Change tracking (as mq do with patches) and versionning (as versionned mq)

mq currently allow to keep a single identifier (patch name) for the multiple changeset that qrefresh create.

Versionned mq allow to restore state of the liquid part you changeset and share it with other people.

History edition extension compatibility

mq (any other extension) keep information about changeset outside the revlog. The force other history editing extension to either: Implement mq compatibility itself, Be incompatible with mq handled changeset, corrupt mq repo.

Sharing volatile part of the history

Sharing the liquid part of the history for review, preview is a complicated issue but an interesting problem.

Ideas and discussion

Original LiquidHg Notes

From http://piratepad.net/eth2IJmQFp

Concept

Liquid HG is a plan to extend Mercurial to more fully support the volatility of MQ, rebase, feature branches, etc., while at the same time maintaining the benefits of immutable history.

The idea is to mark a boundary between history that is permanently fixed and history that is mutable. This boundary will be transmitted between clients via push and pull and will be transparently advanced by certain operations (eg tagging). It can never move backwards.

Changesets above the boundary are considered "liquid" and can be affected by operations like MQ, rebase, etc., and may be subject to garbage collection if they are unreferenced for long periods. Changesets below the boundary ("frozen") are guaranteed not to disappear and are not subject to garbage collection.

Implementation

The liquid boundary is stored as a list of root nodes for liquid branches. All descendants of these nodes are in the liquid set. This list is shared between clients via the pushkey method proposed for sharing bookmarks.

As the liquid list can be optionally empty, no "requires" entry is needed.

Creating the boundary

All changesets are "frozen" until an appropriate command like qnew creates a boundary. Creating a bookmark is another possibility - new changesets on bookmarks may be considered liquid by default.

Moving the boundary

Generally speaking, the boundary should move naturally in the course of normal operations without any special user intervention. The usual methods will be operations like tagging a changeset, merging on to a branch with a non-liquid head, and qfinishing an mq patch.

Another important way to "freeze" a changeset is to "publish" it to a server with "liquidity" turned off, for instance to the "canonical" project server. Everyone pulling from that server will have their liquid boundary moved to the published boundary.

Garbage collection

If bookmarks are enabled, changesets that are not frozen and are not referenced by bookmarks may be garbage-collected.

Compatibility

Old clients obviously won't support pushkey on the liquid list, so they're easy to identify.

New clients with old repo: the liquid list will be effectively empty, so all changesets will be frozen by default

Old client with new repo: doesn't see or update the liquid boundary, mostly works

Pulling from an old client: no effect

Pull by old client: no effect, old client may encounter confusion by seeing removed or obsolete liquid changesets

Push by old client: no effect, new heads will be considered liquid

Pushing to an old client: this is considered 'publishing' and advances the boundary.

Changes to Commands

heads: needs a way to list liquid vs frozen, and identify/filter heads that have bookmark references

log: introduce a marker for liquid csets

push: may require -f or similar to freeze changesets when publishing

Mercurial 1.9 Sprint Notes

From http://titanpad.com/liquidhg-plan

Terms

Behavior of Liquid Boundary

The liquid boundary will always advance in the normal case, requiring direct manual intervention on a server if it must move backwards (much as a strip requires manual intervention and communication today.) Servers which are canonical sources of revision history (for example, http://selenic.com/hg for Mercurial) will either not run the liquid extension, or will run it with liquid.publish=True. When pushing to such a server, the client will advance the liquid boundary to include the heads pushed, and in the case of the latter the server will as well. When pulling from such a server, everything discovered as being present on the server advances the local liquid boundary.

Deathset behavior

Deathsets enumerate the exact changesets they eradicate. If a changeset included in a deathset has a descendant not contained in a deathset, the deathset has no effect on that changeset (we say it's "kept alive" by that descendant).

Pushkey-based deathsets have no effect on frozen changesets, even if that leaves a new head open. Pushkey-based deathsets may be safely garbage collected if they refer entirely to frozen changesets (i.e. changesets behind the liquid boundary), and they may be reduced in size if part of the deathset falls behind the liquid boundary. All pushkey-based deathsets are pulled at any given time, but only those which would evaporate otherwise-liquid changesets are pushed to the server.

Changeset-extra-based deathsets (that is, deathsets in archival changesets) are only propagated if the immediate ancestor of the deathset-holding changeset (always the root of the deathset) is already on the destination server.

Push/pull behavior

Dead liquid changesets are only pushed or pulled if explicitly requested. Dead frozen changesets are only propagated if they are required as a dependency of a killing changeset.


LiquidHG (last edited 2012-10-25 20:57:10 by mpm)