changeset 149:03f314e32058

import some doc
author Pierre-Yves David <pierre-yves.david@logilab.fr>
date Tue, 20 Mar 2012 11:02:11 +0100
parents 8e93e1f67205
children f12fd2410a60
files .hgignore doc/obs-concept.rst doc/obs-implementation.rst doc/vocabulary.rst
diffstat 4 files changed, 397 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/.hgignore
@@ -0,0 +1,2 @@
+syntax: re
+/figures/[^/]+\.png$
new file mode 100644
--- /dev/null
+++ b/doc/obs-concept.rst
@@ -0,0 +1,257 @@
+=========================
+Obsolete concept
+=========================
+
+
+Obsolete marker is a powerful concept that allow mercurial to safely handle
+history rewriting operations. It is a new type of relation between Mercurial
+changesets that track the result of history rewriting operations.
+
+This concept is simple to define and provides a very solid base to:
+
+
+- Very fast history rewriting operations,
+
+- auditable and reversible history rewritting process,
+
+- clean final history,
+
+- share and collaborate on mutable part of the history,
+
+- gracefully handle history rewriting conflict,
+
+- allows various history rewriting UI to collaborate with a underlying common API.
+
+
+-----------------------------------------------------
+Basic concept
+-----------------------------------------------------
+
+
+Every history rewriting operation  stores the information that old rewritten
+changesets has newer version available in a set of changeset.
+
+This simple rules allows to express any possible history rewriting operation:
+
+
+
+
+.. figure:: ./figures/example-1-update.png
+
+    *Updating* a changeset
+
+    Create one obsolete marker: ``([A'] obsolete A)``
+
+
+
+.. figure:: ./figures/example-2-split.png
+
+    *Splitting* a changeset in multiple one
+
+    Create one obsolete marker ``([B1, B2] obsolete B)]``
+
+
+.. figure:: ./figures/example-3-merge.png
+
+    *Merging* multiple changeset in a single one
+
+    Create two obsolete markers ``([C] obsolete A), ([C] obsolete B)``
+
+.. figure:: ./figures/example-4-reorder.png
+
+    *Moving* changeset around
+
+    Reordering those two changesets need two obsolete markers:
+    ``([A'] obsolete A), ([B'] obsolete B)``
+
+
+
+.. figure:: ./figures/example-5-delete.png
+
+    *Removing* a changeset:
+
+    One obselete marker ``([] obsolete B)``
+
+
+To conclude, a single obsolete marker express a relation from **0..n** new
+changesets to **1** old changeset.
+
+-----------------------------------------------------
+Basic Usage
+-----------------------------------------------------
+
+Obsolete markers create a perpendicular history: **a versionned version of the
+changeset graph**. This means that we can have the same feature we have for
+versioned files but applied to changeset:
+
+First: we can display a **coherent view** of the history graph with only a
+single version of your changeset are displayed by the UI.
+
+Second, because obsolete changeset content are still **available**. You can 
+
+    * **browse** the content of your obsolete commit,
+
+    * **compare** newer and older version of a changeset,
+
+    * **restore** content of previously obsolete changeset.
+
+Finally, obsolete marker can be **exchanged between repositories**. You are able to
+share the result on your history rewriting operation with other and **collaborate
+on mutable part of the history**.
+
+Conflicting history rewriting operation can be detected and **resolved** as easily
+as conflicting changes on file.
+
+
+-----------------------------------------------------
+Detecting and solving tricky situation
+-----------------------------------------------------
+
+History rewriting can lead to complex situation. Obsolete marker introduce a
+simple representation this complex reality. But people using complex workflow
+will one day or another you have to face the intrinsics complexity of some
+situation.
+
+This section describe possible situations, define precise set of changesets
+involved in such situation and explains how error case can we automatically
+resolved using available information.
+
+
+obsolete changesets
+````````````````````
+
+Old changesets left behind by obsolete operation are said **obsolete**.
+
+With current version of mercurial, this *obsolete* part is stripped from the
+repository before the end of every rewritting operation.
+
+.. figure:: ./figures/error-obsolete.png
+
+    Rebasing `B` and `C` on `A` (as `B'`, `C'`)
+
+    This rebase operation added two obsolete markers from new changesets to old
+    changesets. These Two old changesets are now part of the *obsolete* part of the
+    history.
+
+In most case the obsolete set will be fully hidden to both UI and discovery so
+user do not have to care about them unless he wants to audit history rewriting
+operation.
+
+Unstable changesets
+```````````````````
+
+While exploring obsolete marker possibility a bit further you way end up with
+*obsolete* changeset with *non-obsolete* children. There is two common ways to
+achieve this:
+
+* Pull a changeset based of an old version of a changeset [#]_.
+
+* Use a partial rewriting operation. For example amend on a changeset with
+  childrens.
+
+*Non-obsolete* changeset based on *obsolete* one are said **unstable**
+
+.. figure:: ./figures/error-unstable.png
+
+    Amend `A` into `A'` leaving `B` behind.
+
+    In this situation we can not consider `B` as *obsolete*.  But we have all
+    necessary data to detect `B` as an *unstable* branch of the history because
+    its parent `A` is *obsolete*. In addition, we have enough data to
+    automatically resolve this instability: we know that the new version of `B`
+    parent (`A`) is `A'`, We can deduce that we should rebase `B` on `A'` to get
+    a stable history again.
+
+Proper warning should be issued when part of the history become unstable. UI
+will be able to use the obsolete marker to automatically suggest resolution to
+the user of even carry them out for him.
+
+
+XXX details automatic resolution for
+
+* movement
+
+* handling deletion
+
+* handling split on multiple head
+
+
+.. [#] For this to happen one needs to explicitly enable exchange of draft
+       changeset. See phase help for details.
+
+The two part of the obsolete set
+``````````````````````````````````````
+
+The previous section show that it could be two kinds of *obsolete* changeset:
+
+
+* *obsolete* changeset with no or *obsolete* only descendants, said **extinct**.
+
+* *obsolete* changeset with *unstable* descendants, said **suspended**.
+
+
+.. figure:: ./figures/error-extinct.png
+
+    Amend `A` and `C` leaving `B` behind.
+
+    In this example we have two *obsolete* changesets: `C` with no *unstable*
+    children is *extinct*. `A` with *unstable* descendant (`B`) is *suspended*.
+    `B` is *unstable* as before.
+
+
+Because nothing outside the obsolete set default on *extinct* changesets, they
+can be safely hidden in the UI and even garbage collected. *Suspended* changeset
+have to stay visible and available until they unstable descendant are rewritten
+in stable version.
+
+
+Conflicting rewriting
+``````````````````````
+
+If people start to concurrently edit the same part of the history they will
+likely meet conflicting situation when a changeset have been rewritten in two
+different versions.
+
+
+.. figure:: ./figures/error-conflicting.png
+
+    Conflicting rewriting of `A` into `A'` and `A''`
+
+This kind of conflict is easy to detect with obsolete marker because an obsolete
+changeset have more than one new version. It may be seen as the multiple heads
+case Mercurial warn you about on pull. It is resolved the same way by a merge of
+A' and A'' that will keep the same parent than `A'` and `A''` with two obsolete
+markers pointing to both `A` and `A'`
+
+.. warning::  TODO: Add a schema of the resolution. (merge A' and A'' with A as
+              ancestor and graft the result of A^)
+
+Allowing multiple new changesets to obsolete a single one allow to distinct a
+splitted changeset from history rewriting conflict.
+
+Reliable history
+``````````````````````
+
+Obsolete marker really help to smooth rewriting operation process. However they
+do not change the fact that **you should only rewrite the mutable part of the
+history**. The phase concept enforce this rules by explicitly defining a
+public immutable set of changeset. Rewriting operation refuse to work on
+public changeset, but they is still some corner case where changesets
+rewritten in the past are made public.
+
+Special rules apply for obsolete marker pointing to public changeset
+
+* Public changesets are excluded from the obsolete set (public changeset are
+  never hidden or candidate to garbage collection)
+
+* *newer* version of public changeset are said **latecomer** and highlighted as
+  error case.
+
+
+Solving such error is easy. Because we know what changeset a *latecomer* try to
+rewrite, we can easily compute a smaller changeset containing only the change
+from the old *public* to the new *latecomer*.
+
+
+.. warning:: add a schema
+
new file mode 100644
--- /dev/null
+++ b/doc/obs-implementation.rst
@@ -0,0 +1,96 @@
+
+.. warning:: This document is still in heavy work in progress
+
+-----------------------------------------------------
+Various technical details
+-----------------------------------------------------
+
+Some stuff that worse to note. some may deserve their own section later.
+
+storing old changeset
+``````````````````````
+
+The new general delta format allow a very efficient storage of two very similar
+changesets. Storing obsolete childrens using general delta takes no more place
+than storing the obsolete diff. Reverted file will even we reused. The whole
+operation will take much less space the strip backup.
+
+
+Abstraction from history rewriting UI
+```````````````````````````````````````````
+
+How Mercurial handle obsolete marker is independent from who decide to create
+them and what actual operation solve error case. Any of the existing history
+rewriting UI (rebase, mq, histedit) can lay obsolete marker and resolve
+situation created by other. To go further a hook system of obsolete marker
+creation would allow each mechanism to collaborate with other though a standard
+and central mechanism.
+
+
+Obsolete marker storage
+```````````````````````````
+
+Obsolete marker will most likely be stored outside standard history. They are
+multiple reasons for that:
+
+
+First, obsolete markers are really perpendicular to standard history there is not
+strong reason to include it here other than convenience.
+
+Second, storing obsolete marker inside standard history means:
+
+
+* A changeset must be created every time an obsolete relation is added. Very
+  inconvenient for delete operation.
+
+* Obsolete marker must be forged at the creation of the new changeset. This
+  is very inconvenient for split operation. And in general it become
+  complicated to fix history afterward in particular when working with older
+  client.
+
+Storing obsolete marker outside history have several pro:
+
+* It ease Exchange of obsolete marker without unnecessary obsolete changeset content
+
+* It allow tuning the actual storage and protocol exchange while maintaining
+  compatibility with older client through the wire (as we do the repository
+  format)
+
+* ease the exchange of obsolete related information during discovery to exchange
+  obsolete changeset relevant to conflict resolution. Exchanging such
+  information deserve a dedicated protocol.
+
+Persistent
+```````````````````````
+
+*Extinct* changeset and obsolete marker will most likely be garbage collected as
+some point. However, archive server may decide to keep them forever in order to
+keep a fully auditable history in it's finest conception.
+
+
+-----------------------------------------------------
+Current status
+-----------------------------------------------------
+
+An experimental implementatione exists. What have been done so far.
+
+
+* 1-1 obsolete marker stored outside history,
+
+* compute obsolete-tip
+
+* obsolete marker exchange through pushkey,
+
+* compute obsolete, unstable, extinct and suspended set.
+
+* hidden extinct changesets for UI.
+
+* Use secret phase to remove from discovery obsolete and unstable changeset (to
+  be improved soon)
+
+* alter rebase to use obsolete marker instead of stripping. (XXX break --keep for now)
+
+* Have an experimental mq-like extension to rewrite history (more on that later)
+
+* Have an extension to update and mq repository according evolution of standard (more on that later)
+
new file mode 100644
--- /dev/null
+++ b/doc/vocabulary.rst
@@ -0,0 +1,42 @@
+
+-----------------------------------------------------
+Vocabulary
+-----------------------------------------------------
+
+.. note:: all terminology is subject to change
+
+:obsolete marker:
+    express a relation from 0..n new changesets to 1 old changeset
+:obsolete changesets:
+    non public changeset target of a obsolete marker
+
+:unstable changeset:
+    changeset not obsolete but with obsolete ancestor
+
+:extinct changeset:
+    obsolete changeset without unstable descendant
+
+:suspended changeset:
+    obsolete changeset with unstable descendant
+
+:obsolete-parents:
+    previous versions of a changeset, through a direct obsolete marker.
+
+:obsolete-children:
+    new versions of a changeset, through a direct obsolete marker.
+
+:obsolete-ancestors:
+    previous versions of a changeset, through any number of obsolete marker
+
+:obsolete-descendant:
+    new versions of a changeset, through any number of obsolete marker
+
+:obsolete-diff:
+    diff between a changeset and it's obsolete parent
+
+:obsolete-tip:
+    obsolete-descendants not obsolete themself.
+
+:conflicting changeset:
+    multiple obsolete-tip for an obsolete changeset through diverging obsolete
+    marker (no changeset split marker)