changeset 161:4e3f25ba5401

More doc and index with sphynx
author Pierre-Yves David <pierre-yves.david@logilab.fr>
date Tue, 20 Mar 2012 19:26:55 +0100
parents 24346b78cd99
children 1a6ae8d8f104 06c942f9bac6
files .hgignore doc/evolve-faq.rst doc/from-mq.rst doc/obs-concept.rst doc/obs-implementation.rst doc/simple-tuto.t doc/vocabulary.rst docs/README docs/conf.py docs/evolve-faq.rst docs/evolve-intro.rst docs/from-mq.rst docs/glossary.rst docs/index.rst docs/obs-concept.rst docs/obs-implementation.rst tests/tutorial.t
diffstat 17 files changed, 1609 insertions(+), 1450 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore
+++ b/.hgignore
@@ -1,2 +1,3 @@
 syntax: re
 /figures/[^/]+\.png$
+^docs/build/
deleted file mode 100644
--- a/doc/evolve-faq.rst
+++ /dev/null
@@ -1,197 +0,0 @@
-========================================
-Introduction to the evolution extension
-========================================
-
-An history rewriting extension
-
-* Using the obsolete marker concept
-
-* Inspired from mq
-
-it is simple to enable::
-
-    $ hg clone http://hg-dev.octopoid.net/hgwebdir.cgi/mutable-history/
-    $ mutable-history/enable.sh > ~/.hgrc
-
-
-
-Quick Guide
-=====================================================================
-
-
-
-Add a changeset: ``commit``
-------------------------------------------------------------
-
-Just use commit as usual.
-
-Rewrite a changeset: ``amend``
-------------------------------------------------------------
-
-A new command ``hg amend`` is added by the extension. it write a new changeset
-combining working-directory parent changes and working directory parent changes.
-
-To understand what the result of amend will be I do use the two following
-aliases  [#]_::
-
-    # diff what amend will look likes
-    pdiff=diff --rev .^
-
-    # status what amend will look likes
-    pstatus=status --rev .^
-
-It take various options to choose the user, the date and the branch of the
-result. see ``hg help amend for detail``
-
-This command can be invoqued on any mutable changeset even changeset with
-children !
-
-
-.. note:: the amend command is very similar to mq's ``qrefresh``, a ``refresh``
-          alias for amend is also available. But note that contrary to
-          ``qrefresh``, ``amend`` does not exclude changes on file not specified
-          on the command line.
-
-          XXX add idank example
-
-
-.. [#] (added by enable.sh)
-
-
-
-Move a changeset: ``graft``
-------------------------------------------------------------
-
-the graft command introduced in 2.0 allows to "copy changes from other branches
-onto the current branch"
-
-The graft command have been altered to be able to create an obsolete marker from
-the copy result to the copy source, acting like changeset movement operation.
-This is achieved using a new flag `-O` (or `old-obsolete`) [#]_.
-
-
-XXX example
-
-.. warning:: when using graft --continue after conflict resolution you **MUST**
-             pass `-O` or `-o` flag again because they are not saved for now
-
-
-.. [#] add this `-O` to graft instead of a dedicated command is probably
-       abusive. But this was very convenient for experimental purpose.
-       This will likely change in non experimental release.
-
-Delete a changeset: ``kill``
-------------------------------------------------------------
-
-A new ``kill`` command allow to remove a changeset.
-
-Just use ``hg kill <some-rev>``.
-
-Moving within the history: ``up`` ``gdown`` and ``gup``
-------------------------------------------------------------
-
-While working on mutable part of the history you often need to move between
-mutable commit.
-
-You just need to use standard update to work with evolve. For convenience, you
-can use ``hg gup`` to move to children commit or ``hg gdown`` to move to working
-directory parent commit.
-
-.. note:: those command only exist for the convenience of getting qpush and qpop
-          feeling back.
-
-          They are 
-
-collapse changesets: ``amend``
-------------------------------------------------------------
-
-you can use amend -c to collapse multiple changeset in a single one.
-
-Move multiple changesets: ``rebase``
-------------------------------------------------------------
-
-You can still use rebase to move whole part of the changeset graph at once.
-
-.. warning:: Beware that rebasing obsolete changeset will result in new
-             conflicting version.
-
-Stabilize history: ``stabilize``
-------------------------------------------------------------
-
-When you rewrite changeset with children without rewriting those children you
-create *unstable* changeset and *suspended obsolete* changeset
-
-.. warning:: ``hg stabilize`` have no --continue to use after conflict
-             resolution. is conflict occurs use::
-
-               $ hg up -C . # cancel the failed merge
-               $ hg stabilize -n # go get a command to execute
-
-.. warning:: stabilization does not handle deletion yet.
-
-.. warning:: obsolete currently rely on secret changeset to not exchange
-             obsolete and unstable changeset.
-
-             XXX details issue here
-
-
-Fix my history afterward: ``kill -n``
-------------------------------------------------------------
-
-sometime you need to create obsolete marker by hand. This may happen when
-upstream applied some of you patches for example.
-
-you can use ``hg kill --new <new-changeset> <old-changeset>`` to add obsolete
-marker.
-
-export to mq: ``synchronize``
-------------------------------------------------------------
-
-Another extension allows to export 
-
-view change to your file
-------------------------------------------------------------
-
-Another extension allows to export 
-
-view diff from the last amend
-------------------------------------------------------------
-
-an odiff alias have been added by enable.sh
-
-:: 
-    [alias]
-    odiff = diff --rev 'limit(obsparents(.),1)' --rev .
-
-view obsolete marker
-------------------------------------------------------------
-
-hgview is the only viewer that support this feature. you need an experimental
-version available here:
-
-    $ hg clone http://hg-dev.octopoid.net/hgwebdir.cgi/hgview/
-
-Prevent my unfinished changeset to get published
-------------------------------------------------------------
-
-The easiest way is to set them in the private phase
-
-Important Note
-=====================================================================
-
-view change to your file
-------------------------------------------------------------
-
-extinct changeset are hidden using the *hidden* feature of mercurial.
-
-only hg log and hgview support it. hg glog or other visual viewer don't.
-
-
-
-
-
-
-
-
-
-
deleted file mode 100644
--- a/doc/from-mq.rst
+++ /dev/null
@@ -1,156 +0,0 @@
-Moving from mq to hg-evolution
-===============================
-
-Cheat sheet
--------------
-
-==============================  ============================================
-mq command                       new equivalent
-==============================  ============================================
-
-qseries                         ``log``
-qnew                            ``commit``
-qrefresh                        ``amend``
-qpop                            ``update`` or ``qdown``
-qpush                           ``update`` or ``gup`` sometimes ``stabilize``
-qrm                             ``kill``
-qfold                           ``amend -c`` (for now, ``collapse`` soon)
-qdiff                           ``odiff``
-
-qfinish                         --
-qimport                         --
-
-
-Replacement details
----------------------
-
-hg qseries
-```````````
-
-All your work in progress are now real changeset all the time.
-
-You can then use standard log to display them. You can use phase revset to
-display unfinished business only and template to have the same kind of compact
-output qseries have.
-
-This will result in something like that::
-
-  [alias]
-  wip = log -r 'not public()' --template='{rev}:{node|short} {description|firstline}\n'
-
-hg qnew
-````````
-
-With evolve you handle standard changeset without additional overlay.
-
-Standard changeset are created using hg commit as usual.
-
-  $ hg commit
-
-If you want to keep the "wip are not pushed" behavior, you are looking for
-setting your changeset in the secret phase using the phase command.
-
-Note that you only need it for the first commit you want to be secret. Later
-commit will inherit their parents phase.
-
-If you always want your new commit to be in the secret phase, your should
-consider updating your configuration:
-
-  [phases]
-  new-commit=secret
-
-hg qref
-````````
-
-A new command from evolution will allow you to rewrite the changeset you are
-currently on. just call:
-
-  $ hg amend
-
-
-This command takes the same option than commit  plus useful switch '-e' (--edit)
-to edit the commit message.
-
-Amend have also a -c switch which allow you to make and explicit amending
-commit before rewriting a changeset.
-
-  $ hg record -m 'feature A'
-  # oups, I forget some stuff
-  $ hg record babar.py
-  $ hg amend -c .^ # .^ refer to "working directoy parent, here 'feature A'
-
-note: refresh is an alias for amend
-
-hg qpop
-`````````
-
-the following command emule the behavior of hg qpop:
-
-  $ hg gdown
-
-If you need to go back to an arbitrary commit you can just us:
-
-  $ hg update
-
-.. note:: gdown and update allow movement with working directory changes applied
-          and gracefully merge them.
-
-hg qpush
-````````
-
-When you rewrite changeset, descendant of rewritten changeset are marked as
-"out of sync". You new to rewrite them on top of the new version of their
-ancestor.
-
-The evolution extension add a command to rewrite the next changeset:
-
-  $ hg stabilize
-
-You can also decide to do it manually using
-
-  $ hg graft -O <old-version>
-
-or 
-
-  $ hg rebase -r <revset for old version> -d .
-
-note: using graft allow you to pick the changeset you want next as the --move
-option of qpush do.
-
-
-hg qrm
-```````
-
-evolution introduce a new command to mark a changeset as "not wanted anymore".
-
-  $ hg kill <revset>
-
-hg qfold
-`````````
-
-
-::
-
-  $ hg up <top changeset>
-  $ amend --edit -c <bottom changeset>
-
-
-or later::
-
-  $ hg collapse # XXX not implemented
-
-  $ hg rebase --collapse # XXX not tested
-
-
-hg qdiff
-`````````
-
-``odiff`` is an alias for `hg diff -r .^` it works as qdiff event outside mq.
-
-
-
-hg qfinish and hg qimport
-````````````````````````````
-
-Is not useful anymore if you want to controll exchange and mutability of
-changeset see the phase feature
deleted file mode 100644
--- a/doc/obs-concept.rst
+++ /dev/null
@@ -1,257 +0,0 @@
-=========================
-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
-
deleted file mode 100644
--- a/doc/obs-implementation.rst
+++ /dev/null
@@ -1,96 +0,0 @@
-
-.. 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)
-
deleted file mode 100644
--- a/doc/simple-tuto.t
+++ /dev/null
@@ -1,702 +0,0 @@
-Mutable History and collaboration
-=====================================================================
-
-
-History mutation
-=====================
-
-.. Albert Beugras
-
-.. René de Robert
-
-
-Here is small introduction of 
-
-Single Developer Usage
-======================
-
-This tutorial shows how to use evolution to replace the basics of *mq*.
-
-
-Amending a changeset
----------------------
-
-
-First there is some setup phase you will understand later.
-
-there is a local repository and a remote one.
-
-Please close your eyes.
-
-  $ hg init local
-  $ cat >> local/.hg/hgrc << EOF
-  > [paths]
-  > remote = ../remote
-  > [ui]
-  > user = Albert Beugras
-  > [diff]
-  > git = 1
-  > [alias]
-  > amend = amend -d '0 0'
-  > tlog = log --template "{node|short}: '{desc}'\n"
-  > ttlog = log --template "{node|short}: '{desc}' ({state})\n"
-  > tglog = log -G --template "{node|short}: '{desc}' {branches}\n"
-  > [extensions]
-  > hgext.graphlog=
-  > hgext.rebase=
-  > EOF
-  $ echo "states=$(echo $(dirname $TESTDIR))/hgext/states.py" >> local/.hg/hgrc
-  $ echo "obsolete=$(echo $(dirname $TESTDIR))/hgext/obsolete.py" >> local/.hg/hgrc
-  $ echo "evolution=$(echo $(dirname $TESTDIR))/hgext/evolution.py" >> local/.hg/hgrc
-  $ hg init remote
-  $ cat >> remote/.hg/hgrc << EOF
-  > [paths]
-  > local = ../local
-  > [ui]
-  > user = René de Robert
-  > [diff]
-  > git = 1
-  > [alias]
-  > amend = amend -d '0 0'
-  > tlog = log --template "{node|short}: '{desc}' {branches}\n"
-  > ttlog = log --template "{node|short}: '{desc}' {state}\n"
-  > tglog = log -G --template "{node|short}: '{desc}' {branches}\n"
-  > [extensions]
-  > hgext.graphlog=
-  > hgext.rebase=
-  > EOF
-  $ echo "states=$(echo $(dirname $TESTDIR))/hgext/states.py" >> remote/.hg/hgrc
-  $ echo "obsolete=$(echo $(dirname $TESTDIR))/hgext/obsolete.py" >> remote/.hg/hgrc
-  $ echo "evolution=$(echo $(dirname $TESTDIR))/hgext/evolution.py" >> remote/.hg/hgrc
-  $ cd local
-
-You can reopen you eyes.
-
-Now we make a first version of our shopping list.
-
-  $ cat  >> shopping << EOF
-  > Spam
-  > Whizzo butter
-  > Albatross
-  > Rat (rather a lot)
-  > Jugged fish
-  > Blancmange
-  > Salmon mousse
-  > EOF
-  $ hg commit -A -m "Monthy Python Shopping list"
-  adding shopping
-
-We share this first version with the outside.
-
-  $ hg push remote
-  pushing to $TESTTMP/remote
-  searching for changes
-  adding changesets
-  adding manifests
-  adding file changes
-  added 1 changesets with 1 changes to 1 files
-
-Later I add additional item to my list
-
-  $ cat >> shopping << EOF
-  > Egg
-  > Suggar
-  > Vinegar
-  > Oil
-  > EOF
-  $ hg commit -m "adding condiment"
-  $ cat >> shopping << EOF
-  > Bananos
-  > Pear
-  > Apple
-  > EOF
-  $ hg commit -m "adding fruit"
-
-I now have the following history:
-
-  $ hg tlog
-  d85de4546133: 'adding fruit'
-  4d5dc8187023: 'adding condiment'
-  7e82d3f3c2cb: 'Monthy Python Shopping list'
-
-But, I just notice, I made a typo in Banana.
-
-  $ hg export tip
-  # HG changeset patch
-  # User test
-  # Date 0 0
-  # Node ID d85de4546133030c82d257bbcdd9b1b416d0c31c
-  # Parent  4d5dc81870237d492284826e21840b2ca00e26d1
-  adding fruit
-  
-  diff --git a/shopping b/shopping
-  --- a/shopping
-  +++ b/shopping
-  @@ -9,3 +9,6 @@
-   Suggar
-   Vinegar
-   Oil
-  +Bananos
-  +Pear
-  +Apple
-
-hopefully. I can use hg amend to rewrite my faulty changeset!
-
-  $ sed -i'' -e s/Bananos/Banana/ shopping
-  $ hg diff
-  diff --git a/shopping b/shopping
-  --- a/shopping
-  +++ b/shopping
-  @@ -9,6 +9,6 @@
-   Suggar
-   Vinegar
-   Oil
-  -Bananos
-  +Banana
-   Pear
-   Apple
-  $ hg amend
-  abort: can not rewrite immutable changeset d85de4546133
-  [255]
-
-By default all changeset are considered "published" and can't be rewrittent.
-
- $ hg ttlog
-
-You need to enable a mutable state in your repo the "ready" one
-
-  $ hg states ready --clever
-  $ hg ttlog
-  d85de4546133: 'adding fruit' (ready)
-  4d5dc8187023: 'adding condiment' (ready)
-  7e82d3f3c2cb: 'Monthy Python Shopping list' (published)
-
-Notice that changeset you already shared with the outside have been keep
-published.
-
-The changeset we want to rewrite is now in a mutable state.
-
-  $ hg amend
-
-A new changeset with the right diff replace the wrong one.
-
-  $ hg tlog
-  0cacb48f4482: 'adding fruit'
-  4d5dc8187023: 'adding condiment'
-  7e82d3f3c2cb: 'Monthy Python Shopping list'
-  $ hg export tip
-  # HG changeset patch
-  # User test
-  # Date 0 0
-  # Node ID 0cacb48f44828d2fd31c4e45e18fde32a5b2f07b
-  # Parent  4d5dc81870237d492284826e21840b2ca00e26d1
-  adding fruit
-  
-  diff --git a/shopping b/shopping
-  --- a/shopping
-  +++ b/shopping
-  @@ -9,3 +9,6 @@
-   Suggar
-   Vinegar
-   Oil
-  +Banana
-  +Pear
-  +Apple
-
-Getting Ride of branchy history
-----------------------------------
-
-While I was working on my list. someone help made a change remotly.
-
-close your eyes
-
-  $ cd ../remote
-  $ hg up -q
-  $ sed -i'' -e 's/Spam/Spam Spam Spam/' shopping
-  $ hg ci -m 'SPAM'
-  $ cd ../local
-
-open your eyes
-
-  $ hg pull remote
-  pulling from $TESTTMP/remote
-  searching for changes
-  adding changesets
-  adding manifests
-  adding file changes
-  added 1 changesets with 1 changes to 1 files (+1 heads)
-  (run 'hg heads .' to see heads, 'hg merge' to merge)
-
-I now have a new heads. Note that the remote head is immutable
-
-  $ hg ttlog
-  9ca060c80d74: 'SPAM' (published)
-  0cacb48f4482: 'adding fruit' (ready)
-  4d5dc8187023: 'adding condiment' (ready)
-  7e82d3f3c2cb: 'Monthy Python Shopping list' (published)
-  $ hg tglog -r "::(9ca060c80d74 + 0cacb48f4482)"
-  o  9ca060c80d74: 'SPAM'
-  |
-  | @  0cacb48f4482: 'adding fruit'
-  | |
-  | o  4d5dc8187023: 'adding condiment'
-  |/
-  o  7e82d3f3c2cb: 'Monthy Python Shopping list'
-  
-
-instead of merging my head with the new one. I'm going to rebase my work
-
-  $ hg diff
-  $ hg rebase -d 9ca060c80d74 -s 4d5dc8187023
-  merging shopping
-  merging shopping
-  merging shopping
-  merging shopping
-
-
-My local work is now rebase on the remote one.
-
-  $ hg kill e7a71e229632 ad97bbd3e37d # XXX fix me instead
-  $ hg ttlog
-  387187ad9bd9: 'adding fruit' (ready)
-  dfd3a2d7691e: 'adding condiment' (ready)
-  9ca060c80d74: 'SPAM' (published)
-  7e82d3f3c2cb: 'Monthy Python Shopping list' (published)
-  $ hg tglog -r '::.'
-  @  387187ad9bd9: 'adding fruit'
-  |
-  o  dfd3a2d7691e: 'adding condiment'
-  |
-  o  9ca060c80d74: 'SPAM'
-  |
-  o  7e82d3f3c2cb: 'Monthy Python Shopping list'
-  
-
-Removing changeset
-------------------------
-
-I add new item to my list
-
-  $ cat >> shopping << EOF
-  > car
-  > bus
-  > plane
-  > boat
-  > EOF
-  $ hg ci -m 'transport'
-  $ hg ttlog
-  d58c77aa15d7: 'transport' (ready)
-  387187ad9bd9: 'adding fruit' (ready)
-  dfd3a2d7691e: 'adding condiment' (ready)
-  9ca060c80d74: 'SPAM' (published)
-  7e82d3f3c2cb: 'Monthy Python Shopping list' (published)
-
-I have a new commit but I realize that don't want it. (transport shop list does
-not fit well in my standard shopping list)
-
-  $ hg kill . # . is for working directory parent.
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  working directory now at 387187ad9bd9
-
-The silly changeset is gone.
-
-  $ hg ttlog
-  387187ad9bd9: 'adding fruit' (ready)
-  dfd3a2d7691e: 'adding condiment' (ready)
-  9ca060c80d74: 'SPAM' (published)
-  7e82d3f3c2cb: 'Monthy Python Shopping list' (published)
-
-Reordering changeset
-------------------------
-
-
-We create two changeset.
-
-
-  $ cat >> shopping << EOF
-  > Shampoo
-  > Toothbrush
-  > ... More bathroom stuff to come
-  > Towel
-  > Soap
-  > EOF
-  $ hg ci -m 'bathroom stuff' -q # XXX remove the -q
-
-  $ sed -i'' -e 's/Spam/Spam Spam Spam/g' shopping
-  $ hg ci -m 'SPAM SPAM'
-  $ hg ttlog
-  c48f32fb1787: 'SPAM SPAM' (ready)
-  8d39a843582d: 'bathroom stuff' (ready)
-  387187ad9bd9: 'adding fruit' (ready)
-  dfd3a2d7691e: 'adding condiment' (ready)
-  9ca060c80d74: 'SPAM' (published)
-  7e82d3f3c2cb: 'Monthy Python Shopping list' (published)
-
-.. note: don't amend changeset 7e82d3f3c2cb or 9ca060c80d74 as they are
-immutable.
-
-I now want to push to remote all my change but the bathroom one that i'm not totally happy with yet.
-
-To be able to push "SPAM SPAM" I need a version of "SPAM SPAM" not children of "bathroom stuff"
-
-You can use rebase or relocate for that:
-
-  $ hg relocate 'p1(8d39a843582d)' --traceback
-  merging shopping
-  $ hg tglog -r '::(. + 8d39a843582d)'
-  @  02e33960e937: 'SPAM SPAM'
-  |
-  | o  8d39a843582d: 'bathroom stuff'
-  |/
-  o  387187ad9bd9: 'adding fruit'
-  |
-  o  dfd3a2d7691e: 'adding condiment'
-  |
-  o  9ca060c80d74: 'SPAM'
-  |
-  o  7e82d3f3c2cb: 'Monthy Python Shopping list'
-  
-
-We have a new SPAM SPAM version without the bathroom stuff
-
-  $ grep Spam shopping  # enouth spamm
-  Spam Spam Spam Spam Spam Spam Spam Spam Spam
-  $ grep Toothbrush shopping # no Toothbrush
-  [1]
-  $ hg export .
-  # HG changeset patch
-  # User test
-  # Date 0 0
-  # Node ID 02e33960e937ad1bd59241ebdafd7a2494240ddf
-  # Parent  387187ad9bd9d8f9a00a9fa804a26231db547429
-  SPAM SPAM
-  
-  diff --git a/shopping b/shopping
-  --- a/shopping
-  +++ b/shopping
-  @@ -1,4 +1,4 @@
-  -Spam Spam Spam
-  +Spam Spam Spam Spam Spam Spam Spam Spam Spam
-   Whizzo butter
-   Albatross
-   Rat (rather a lot)
-
-we can now push our change:
-
-  $ hg push -r . remote
-  pushing to $TESTTMP/remote
-  searching for changes
-  adding changesets
-  adding manifests
-  adding file changes
-  added 3 changesets with 3 changes to 1 files
-
-for simplicity shake we relocate the bathroom changeset
-
-  $ hg relocate -r 8d39a843582d 02e33960e937
-  merging shopping
-
-
-Splitting change
-------------------
-
-To be done (currently achieve with "two commit + debugobsolete")
-
-Collapsing change
-------------------
-
-To be done (currently achieve with "revert + debugobsolete" or "rebase --collapse")
-
-collaboration
-====================
-
-
-sharing mutable changeset
-----------------------------
-
-To share mutable changeset with other just check that both have the "ready"
-state activated. Otherwise you will get the previously observe behavior where
-exchanged changeset are automatically published.
-
-  $ cd ../remote
-  $ hg states 
-  published
-
-The remote repository have only the immutable "published" state activated. Any
-changeset echanged from "local" to "remote" will be set in the publised state:
-
-  $ hg -R ../local push -f remote # XXX we should pull but the support is awful
-  pushing to $TESTTMP/remote
-  searching for changes
-  adding changesets
-  adding manifests
-  adding file changes
-  added 1 changesets with 1 changes to 1 files
-  $ hg ttlog
-  a3515e5d0332: 'bathroom stuff' published
-  02e33960e937: 'SPAM SPAM' published
-  387187ad9bd9: 'adding fruit' published
-  dfd3a2d7691e: 'adding condiment' published
-  9ca060c80d74: 'SPAM' published
-  7e82d3f3c2cb: 'Monthy Python Shopping list' published
-
-
-
-We do not want to publish the "bathroom changeset". Let's rollback the last transaction
-
-  $ hg rollback
-  repository tip rolled back to revision 4 (undo push)
-  working directory now based on revision 1
-  $ hg ttlog
-  02e33960e937: 'SPAM SPAM' published
-  387187ad9bd9: 'adding fruit' published
-  dfd3a2d7691e: 'adding condiment' published
-  9ca060c80d74: 'SPAM' published
-  7e82d3f3c2cb: 'Monthy Python Shopping list' published
-  $ rm ../local/.hg/states/published-heads     # XXX USE --exact
-  $ hg -R ../local publish 02e33960e937 # XXX FIX THE BUG
-
-To enable the mutable "ready" state in a repository, use the states command.
-
-  $ hg states ready
-  $ hg states 
-  published
-  ready
-
-I can nom exchange mutable changeset between "remote" and "local" repository.
-
-  $ hg pull local # XXX We pull too much stuff
-  pulling from $TESTTMP/local
-  searching for changes
-  adding changesets
-  adding manifests
-  adding file changes
-  added 10 changesets with 10 changes to 1 files (+5 heads)
-  (run 'hg heads' to see heads, 'hg merge' to merge)
-  $ hg ttlog
-  a3515e5d0332: 'bathroom stuff' ready
-  02e33960e937: 'SPAM SPAM' published
-  387187ad9bd9: 'adding fruit' published
-  dfd3a2d7691e: 'adding condiment' published
-  9ca060c80d74: 'SPAM' published
-  7e82d3f3c2cb: 'Monthy Python Shopping list' published
-
-Rebasing out-of-sync change after update
-----------------------------------------------
-
-Remotely someone add a new changeset on top of our mutable "bathroom" on.
-
-  $ hg up a3515e5d0332 -q
-  $ cat >> shopping << EOF
-  > Giraffe
-  > Rhino
-  > Lion
-  > Bear
-  > EOF
-  $ hg ci -m 'animals' -q # XXX remove the -q
-
-While this time locally, we rebase the updated the "bathroom changeset"
-
-  $ cd ../local
-  $ hg up a3515e5d0332 -q
-  $ sed -i'' -e 's/... More bathroom stuff to come/Bath Robe/' shopping
-  $ hg amend
-  $ hg tlog
-  962d3a7d27ad: 'bathroom stuff'
-  02e33960e937: 'SPAM SPAM'
-  387187ad9bd9: 'adding fruit'
-  dfd3a2d7691e: 'adding condiment'
-  9ca060c80d74: 'SPAM'
-  7e82d3f3c2cb: 'Monthy Python Shopping list'
-
-
-When we pull from remote again we get an unstable state!
-
-  $ hg pull remote
-  pulling from $TESTTMP/remote
-  searching for changes
-  adding changesets
-  adding manifests
-  adding file changes
-  added 1 changesets with 1 changes to 1 files (+1 heads)
-  (run 'hg heads .' to see heads, 'hg merge' to merge)
-  $ hg tlog
-  0b061760b677: 'animals'
-  962d3a7d27ad: 'bathroom stuff'
-  a3515e5d0332: 'bathroom stuff'
-  02e33960e937: 'SPAM SPAM'
-  387187ad9bd9: 'adding fruit'
-  dfd3a2d7691e: 'adding condiment'
-  9ca060c80d74: 'SPAM'
-  7e82d3f3c2cb: 'Monthy Python Shopping list'
-
-The new changeset "animal" is based one an old changeset of "bathroom". You can
-see both version showing up the log.
-
-  $ hg tglog -r '::(962d3a7d27ad + 0b061760b677)'
-  o  0b061760b677: 'animals'
-  |
-  | @  962d3a7d27ad: 'bathroom stuff'
-  | |
-  o |  a3515e5d0332: 'bathroom stuff'
-  |/
-  o  02e33960e937: 'SPAM SPAM'
-  |
-  o  387187ad9bd9: 'adding fruit'
-  |
-  o  dfd3a2d7691e: 'adding condiment'
-  |
-  o  9ca060c80d74: 'SPAM'
-  |
-  o  7e82d3f3c2cb: 'Monthy Python Shopping list'
-  
-
-In hgviewn there is a nice doted relation highlighting 962d3a7d27ad  is a new
-version of a3515e5d0332. this is not yet ported to graphlog.
-
-To resolve this unstable state, you need to relocate 0b061760b677 onto
-962d3a7d27ad the "hg evolve" will make the thinking for you and suggest it to
-you.
-
-  $ hg evolve
-  hg relocate --rev 0b061760b677 962d3a7d27ad
-
-Let's do it
-
-  $ hg relocate --rev 0b061760b677 962d3a7d27ad
-  merging shopping
-
-The old vesion of bathroom is hidden again now.
-
-  $ hg tlog
-  39a85a192689: 'animals'
-  962d3a7d27ad: 'bathroom stuff'
-  02e33960e937: 'SPAM SPAM'
-  387187ad9bd9: 'adding fruit'
-  dfd3a2d7691e: 'adding condiment'
-  9ca060c80d74: 'SPAM'
-  7e82d3f3c2cb: 'Monthy Python Shopping list'
-
-We can push this evolution to remote
-
-  $ hg push -f remote # XXX should not require -f
-  pushing to $TESTTMP/remote
-  searching for changes
-  adding changesets
-  adding manifests
-  adding file changes
-  added 2 changesets with 2 changes to 1 files (+1 heads)
-
-remote get a warning that current working directory is based on an obsolete changeset
-
-  $ cd ../remote
-  $ hg up . # XXX "loulz"
-  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  Working directory parent is obsolete
-
-  $ hg up 39a85a192689
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-
-Relocating out-of-sync change after kill
-----------------------------------------------
-
-The remote guy keep working
-
-  $ sed -i'' -e 's/Spam/Spam Spam Spam Spam/g' shopping
-  $ hg commit -m "SPAM SPAM SPAM"
-
-Work I can keep getting localy
-
-  $ cd ../local
-  $ hg pull remote
-  pulling from $TESTTMP/remote
-  searching for changes
-  adding changesets
-  adding manifests
-  adding file changes
-  added 1 changesets with 1 changes to 1 files
-  (run 'hg update' to get a working copy)
-  $ hg tlog
-  e768beeb835c: 'SPAM SPAM SPAM'
-  39a85a192689: 'animals'
-  962d3a7d27ad: 'bathroom stuff'
-  02e33960e937: 'SPAM SPAM'
-  387187ad9bd9: 'adding fruit'
-  dfd3a2d7691e: 'adding condiment'
-  9ca060c80d74: 'SPAM'
-  7e82d3f3c2cb: 'Monthy Python Shopping list'
-
-In the mean time I noticed you can't buy animals in a super market and I kill the animal changeset:
-
-  $ hg kill 39a85a192689 # issue warning here
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  working directory now at 962d3a7d27ad
-
-The animals changeset is still displayed because the "SPAM SPAM SPAM" changeset
-is neither dead or obsolete.  My repository is in an unstable state again.
-
-  $ hg tlog 
-  e768beeb835c: 'SPAM SPAM SPAM'
-  39a85a192689: 'animals'
-  962d3a7d27ad: 'bathroom stuff'
-  02e33960e937: 'SPAM SPAM'
-  387187ad9bd9: 'adding fruit'
-  dfd3a2d7691e: 'adding condiment'
-  9ca060c80d74: 'SPAM'
-  7e82d3f3c2cb: 'Monthy Python Shopping list'
-  $ hg tglog  -r '::e768beeb835c'
-  o  e768beeb835c: 'SPAM SPAM SPAM'
-  |
-  o  39a85a192689: 'animals'
-  |
-  @  962d3a7d27ad: 'bathroom stuff'
-  |
-  o  02e33960e937: 'SPAM SPAM'
-  |
-  o  387187ad9bd9: 'adding fruit'
-  |
-  o  dfd3a2d7691e: 'adding condiment'
-  |
-  o  9ca060c80d74: 'SPAM'
-  |
-  o  7e82d3f3c2cb: 'Monthy Python Shopping list'
-  
-
-#  $ hg evolve # XXX not ready yet
-#  hg relocate --rev  e768beeb835c 962d3a7d27ad
-
-  $ hg relocate -r  e768beeb835c 'p1(39a85a192689)'
-  merging shopping
-
-  $ hg tlog 
-  19098f8178f3: 'SPAM SPAM SPAM'
-  962d3a7d27ad: 'bathroom stuff'
-  02e33960e937: 'SPAM SPAM'
-  387187ad9bd9: 'adding fruit'
-  dfd3a2d7691e: 'adding condiment'
-  9ca060c80d74: 'SPAM'
-  7e82d3f3c2cb: 'Monthy Python Shopping list'
-
-Handling Conflicting amend
-----------------------------------------------
-
-We can detect that multiple diverging//conflicting amend have been made. There
-will be a "evol-merge" command to merge conflicting amend
-
-collaboration
-====================
-
-Turning changeset immutable
-----------------------------------------------
-
-* push on published//only repo
-
-* tag
-
-* explicite published command
-
-Handling Invalid amend on published changeset
-----------------------------------------------
-
-you can't amend published changeset. changeset that do this will have an "invalid amend" obsolete-status
-
deleted file mode 100644
--- a/doc/vocabulary.rst
+++ /dev/null
@@ -1,42 +0,0 @@
-
------------------------------------------------------
-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)
new file mode 100644
--- /dev/null
+++ b/docs/README
@@ -0,0 +1,3 @@
+doc generated with sphinx. tutorial exported using sphinxedhg
+
+http://hg.piranha.org.ua/sphinxedhg/
new file mode 100644
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,124 @@
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = []
+#autoclass_content = 'both'
+# Add any paths that contain templates here, relative to this directory.
+#templates_path = []
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General substitutions.
+project = 'Obsolete experimentation'
+copyright = '2010-2011, pierre-yves.david@logilab.fr'
+
+# The default replacements for |version| and |release|, also used in various
+# other places throughout the built documents.
+#
+# The short X.Y version.
+version = '0.0'
+# The full version, including alpha/beta/rc tags.
+release = '0.0'
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+unused_docs = []
+
+# List of directories, relative to source directories, that shouldn't be searched
+# for source files.
+#exclude_dirs = []
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+# Options for HTML output
+# -----------------------
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+#html_style = 'sphinx-default.css'
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+html_title = project
+#html_theme = 
+html_theme_path = ['.']
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (within the static path) to place at the top of
+# the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['.static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+html_use_modindex = False
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+#html_copy_source = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = '.html'
+
+# Output file base name for HTML help builder.
+#htmlhelp_basename = ''
new file mode 100644
--- /dev/null
+++ b/docs/evolve-faq.rst
@@ -0,0 +1,175 @@
+
+---------------------------------------------------------------------
+Evolve How To
+---------------------------------------------------------------------
+
+
+Add a changeset: ``commit``
+------------------------------------------------------------
+
+Just use commit as usual.
+
+Rewrite a changeset: ``amend``
+------------------------------------------------------------
+
+A new command ``hg amend`` is added by the extension. it write a new changeset
+combining working-directory parent changes and working directory parent changes.
+
+To understand what the result of amend will be I do use the two following
+aliases  [#]_::
+
+    # diff what amend will look likes
+    pdiff=diff --rev .^
+
+    # status what amend will look likes
+    pstatus=status --rev .^
+
+It take various options to choose the user, the date and the branch of the
+result. see ``hg help amend for detail``
+
+This command can be invoqued on any mutable changeset even changeset with
+children !
+
+
+.. note:: the amend command is very similar to mq's ``qrefresh``, a ``refresh``
+          alias for amend is also available. But note that contrary to
+          ``qrefresh``, ``amend`` does not exclude changes on file not specified
+          on the command line.
+
+          XXX add idank example
+
+
+.. [#] (added by enable.sh)
+
+
+Move a changeset: ``graft``
+------------------------------------------------------------
+
+the graft command introduced in 2.0 allows to "copy changes from other branches
+onto the current branch"
+
+The graft command have been altered to be able to create an obsolete marker from
+the copy result to the copy source, acting like changeset movement operation.
+This is achieved using a new flag `-O` (or `old-obsolete`) [#]_.
+
+
+XXX example
+
+.. warning:: when using graft --continue after conflict resolution you **MUST**
+             pass `-O` or `-o` flag again because they are not saved for now
+
+
+.. [#] add this `-O` to graft instead of a dedicated command is probably
+       abusive. But this was very convenient for experimental purpose.
+       This will likely change in non experimental release.
+
+Delete a changeset: ``kill``
+------------------------------------------------------------
+
+A new ``kill`` command allow to remove a changeset.
+
+Just use ``hg kill <some-rev>``.
+
+Moving within the history: ``up`` ``gdown`` and ``gup``
+------------------------------------------------------------
+
+While working on mutable part of the history you often need to move between
+mutable commit.
+
+You just need to use standard update to work with evolve. For convenience, you
+can use ``hg gup`` to move to children commit or ``hg gdown`` to move to working
+directory parent commit.
+
+.. note:: those command only exist for the convenience of getting qpush and qpop
+          feeling back.
+
+          They are 
+
+collapse changesets: ``amend``
+------------------------------------------------------------
+
+you can use amend -c to collapse multiple changeset in a single one.
+
+Move multiple changesets: ``rebase``
+------------------------------------------------------------
+
+You can still use rebase to move whole part of the changeset graph at once.
+
+.. warning:: Beware that rebasing obsolete changeset will result in new
+             conflicting version.
+
+Stabilize history: ``stabilize``
+------------------------------------------------------------
+
+When you rewrite changeset with children without rewriting those children you
+create *unstable* changeset and *suspended obsolete* changeset
+
+.. warning:: ``hg stabilize`` have no --continue to use after conflict
+             resolution. is conflict occurs use::
+
+               $ hg up -C . # cancel the failed merge
+               $ hg stabilize -n # go get a command to execute
+
+.. warning:: stabilization does not handle deletion yet.
+
+.. warning:: obsolete currently rely on secret changeset to not exchange
+             obsolete and unstable changeset.
+
+             XXX details issue here
+
+
+Fix my history afterward: ``kill -n``
+------------------------------------------------------------
+
+sometime you need to create obsolete marker by hand. This may happen when
+upstream applied some of you patches for example.
+
+you can use ``hg kill --new <new-changeset> <old-changeset>`` to add obsolete
+marker.
+
+view change to your file
+------------------------------------------------------------
+
+Another extension allows to export 
+
+view diff from the last amend
+------------------------------------------------------------
+
+an odiff alias have been added by enable.sh
+
+:: 
+    [alias]
+    odiff = diff --rev 'limit(obsparents(.),1)' --rev .
+
+view obsolete marker
+------------------------------------------------------------
+
+hgview is the only viewer that support this feature. you need an experimental
+version available here:
+
+    $ hg clone http://hg-dev.octopoid.net/hgwebdir.cgi/hgview/
+
+Prevent my unfinished changeset to get published
+------------------------------------------------------------
+
+The easiest way is to set them in the private phase
+
+Important Note
+=====================================================================
+
+view change to your file
+------------------------------------------------------------
+
+extinct changeset are hidden using the *hidden* feature of mercurial.
+
+only hg log and hgview support it. hg glog or other visual viewer don't.
+
+
+
+
+
+
+
+
+
+
new file mode 100644
--- /dev/null
+++ b/docs/evolve-intro.rst
@@ -0,0 +1,14 @@
+----------------------------------------
+Introduction to the evolve extension
+----------------------------------------
+
+An history rewriting extension
+
+* Using the obsolete marker concept
+
+* Inspired from mq
+
+it is simple to enable::
+
+    $ hg clone http://hg-dev.octopoid.net/hgwebdir.cgi/mutable-history/
+    $ mutable-history/enable.sh > ~/.hgrc
new file mode 100644
--- /dev/null
+++ b/docs/from-mq.rst
@@ -0,0 +1,165 @@
+-------------------------------------------
+From MQ To Evolve, The Refugee Book
+-------------------------------------------
+
+Cheat sheet
+-------------
+
+==============================  ============================================
+mq command                       new equivalent
+==============================  ============================================
+
+qseries                         ``log``
+qnew                            ``commit``
+qrefresh                        ``amend``
+qpop                            ``update`` or ``qdown``
+qpush                           ``update`` or ``gup`` sometimes ``stabilize``
+qrm                             ``kill``
+qfold                           ``amend -c`` (for now, ``collapse`` soon)
+qdiff                           ``odiff``
+
+qfinish                         --
+qimport                         --
+
+
+Replacement details
+---------------------
+
+hg qseries
+```````````
+
+All your work in progress are now real changeset all the time.
+
+You can then use standard log to display them. You can use phase revset to
+display unfinished business only and template to have the same kind of compact
+output qseries have.
+
+This will result in something like that::
+
+  [alias]
+  wip = log -r 'not public()' --template='{rev}:{node|short} {description|firstline}\n'
+
+hg qnew
+````````
+
+With evolve you handle standard changeset without additional overlay.
+
+Standard changeset are created using hg commit as usual.
+
+  $ hg commit
+
+If you want to keep the "wip are not pushed" behavior, you are looking for
+setting your changeset in the secret phase using the phase command.
+
+Note that you only need it for the first commit you want to be secret. Later
+commit will inherit their parents phase.
+
+If you always want your new commit to be in the secret phase, your should
+consider updating your configuration:
+
+  [phases]
+  new-commit=secret
+
+hg qref
+````````
+
+A new command from evolution will allow you to rewrite the changeset you are
+currently on. just call:
+
+  $ hg amend
+
+
+This command takes the same option than commit  plus useful switch '-e' (--edit)
+to edit the commit message.
+
+Amend have also a -c switch which allow you to make and explicit amending
+commit before rewriting a changeset.
+
+  $ hg record -m 'feature A'
+  # oups, I forget some stuff
+  $ hg record babar.py
+  $ hg amend -c .^ # .^ refer to "working directoy parent, here 'feature A'
+
+note: refresh is an alias for amend
+
+hg qpop
+`````````
+
+the following command emule the behavior of hg qpop:
+
+  $ hg gdown
+
+If you need to go back to an arbitrary commit you can just us:
+
+  $ hg update
+
+.. note:: gdown and update allow movement with working directory changes applied
+          and gracefully merge them.
+
+hg qpush
+````````
+
+When you rewrite changeset, descendant of rewritten changeset are marked as
+"out of sync". You new to rewrite them on top of the new version of their
+ancestor.
+
+The evolution extension add a command to rewrite the next changeset:
+
+  $ hg stabilize
+
+You can also decide to do it manually using
+
+  $ hg graft -O <old-version>
+
+or 
+
+  $ hg rebase -r <revset for old version> -d .
+
+note: using graft allow you to pick the changeset you want next as the --move
+option of qpush do.
+
+
+hg qrm
+```````
+
+evolution introduce a new command to mark a changeset as "not wanted anymore".
+
+  $ hg kill <revset>
+
+hg qfold
+`````````
+
+
+::
+
+  $ hg up <top changeset>
+  $ amend --edit -c <bottom changeset>
+
+
+or later::
+
+  $ hg collapse # XXX not implemented
+
+  $ hg rebase --collapse # XXX not tested
+
+
+hg qdiff
+`````````
+
+``odiff`` is an alias for `hg diff -r .^` it works as qdiff event outside mq.
+
+
+
+hg qfinish and hg qimport
+````````````````````````````
+
+Is not useful anymore if you want to controll exchange and mutability of
+changeset see the phase feature
+
+
+
+hg qcommit
+```````````````
+
+If you really need to send patches through a versionned mq patches you should
+look at the qsync extension.
new file mode 100644
--- /dev/null
+++ b/docs/glossary.rst
@@ -0,0 +1,41 @@
+-----------------------------------------------------
+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)
new file mode 100644
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,58 @@
+========================================
+Safe Mutable History
+========================================
+
+
+Here are various Materials on planned improvement to mercurial regarding
+rewriting mutable history.
+
+The effort is splitted in two part:
+
+ * The **obsolete marker** concept that
+ 
+ 
+ 
+    add an alternative to strip to remove changeset from a repository.
+
+ * The changeset evolution UI
+
+    to replace mq.
+ 
+ 
+ adding in mercurial core an new concept of **obsolete marker** in mercurial
+   core,
+
+ * 
+
+
+
+
+
+Evolve: A new UI to replace MQ
+=================================
+
+For user
+
+.. toctree::
+   :maxdepth: 1
+
+   evolve-intro
+   tutorial
+   evolve-faq
+   from-mq
+
+A new UI to replace MQ
+=================================
+
+for dev and advanced user
+
+
+.. toctree::
+   :maxdepth: 1
+
+   obs-concept
+   glossary
+   obs-implementation
+
+
+Big flasshy warning on current remaining issue
new file mode 100644
--- /dev/null
+++ b/docs/obs-concept.rst
@@ -0,0 +1,254 @@
+-------------------------
+Obsolete Marker 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/docs/obs-implementation.rst
@@ -0,0 +1,97 @@
+
+-----------------------------------------------------
+Implementation of Obsolete Marker
+-----------------------------------------------------
+.. 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/tests/tutorial.t
@@ -0,0 +1,677 @@
+Mutable History and collaboration
+=====================================================================
+
+
+.. warning:: need heavy update
+
+
+Single Developer Usage
+======================
+
+This tutorial shows how to use evolution to replace the basics of *mq*.
+
+
+Amending a changeset
+---------------------
+
+
+First there is some setup phase you will understand later.
+
+there is a local repository and a remote one.
+
+Please close your eyes.
+
+  $ hg init local
+  $ cat >> local/.hg/hgrc << EOF
+  > [paths]
+  > remote = ../remote
+  > [ui]
+  > user = Albert Beugras
+  > [diff]
+  > git = 1
+  > [alias]
+  > amend = amend -d '0 0'
+  > tlog = log --template "{node|short}: '{desc}'\n"
+  > ttlog = log --template "{node|short}: '{desc}' ({state})\n"
+  > tglog = log -G --template "{node|short}: '{desc}' {branches}\n"
+  > [extensions]
+  > hgext.graphlog=
+  > hgext.rebase=
+  > EOF
+  $ echo "states=$(echo $(dirname $TESTDIR))/hgext/states.py" >> local/.hg/hgrc
+  $ echo "obsolete=$(echo $(dirname $TESTDIR))/hgext/obsolete.py" >> local/.hg/hgrc
+  $ echo "evolution=$(echo $(dirname $TESTDIR))/hgext/evolution.py" >> local/.hg/hgrc
+  $ hg init remote
+  $ cat >> remote/.hg/hgrc << EOF
+  > [paths]
+  > local = ../local
+  > [ui]
+  > user = René de Robert
+  > [diff]
+  > git = 1
+  > [alias]
+  > amend = amend -d '0 0'
+  > tlog = log --template "{node|short}: '{desc}' {branches}\n"
+  > ttlog = log --template "{node|short}: '{desc}' {state}\n"
+  > tglog = log -G --template "{node|short}: '{desc}' {branches}\n"
+  > [extensions]
+  > hgext.graphlog=
+  > hgext.rebase=
+  > EOF
+  $ echo "states=$(echo $(dirname $TESTDIR))/hgext/states.py" >> remote/.hg/hgrc
+  $ echo "obsolete=$(echo $(dirname $TESTDIR))/hgext/obsolete.py" >> remote/.hg/hgrc
+  $ echo "evolution=$(echo $(dirname $TESTDIR))/hgext/evolution.py" >> remote/.hg/hgrc
+  $ cd local
+
+You can reopen you eyes.
+
+Now we make a first version of our shopping list.
+
+  $ cat  >> shopping << EOF
+  > Spam
+  > Whizzo butter
+  > Albatross
+  > Rat (rather a lot)
+  > Jugged fish
+  > Blancmange
+  > Salmon mousse
+  > EOF
+  $ hg commit -A -m "Monthy Python Shopping list"
+  adding shopping
+
+We share this first version with the outside.
+
+  $ hg push remote
+  pushing to $TESTTMP/remote
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+
+Later I add additional item to my list
+
+  $ cat >> shopping << EOF
+  > Egg
+  > Suggar
+  > Vinegar
+  > Oil
+  > EOF
+  $ hg commit -m "adding condiment"
+  $ cat >> shopping << EOF
+  > Bananos
+  > Pear
+  > Apple
+  > EOF
+  $ hg commit -m "adding fruit"
+
+I now have the following history:
+
+  $ hg tlog
+  d85de4546133: 'adding fruit'
+  4d5dc8187023: 'adding condiment'
+  7e82d3f3c2cb: 'Monthy Python Shopping list'
+
+But, I just notice, I made a typo in Banana.
+
+  $ hg export tip
+  # HG changeset patch
+  # User test
+  # Date 0 0
+  # Node ID d85de4546133030c82d257bbcdd9b1b416d0c31c
+  # Parent  4d5dc81870237d492284826e21840b2ca00e26d1
+  adding fruit
+  
+  diff --git a/shopping b/shopping
+  --- a/shopping
+  +++ b/shopping
+  @@ -9,3 +9,6 @@
+   Suggar
+   Vinegar
+   Oil
+  +Bananos
+  +Pear
+  +Apple
+
+hopefully. I can use hg amend to rewrite my faulty changeset!
+
+  $ sed -i'' -e s/Bananos/Banana/ shopping
+  $ hg diff
+  diff --git a/shopping b/shopping
+  --- a/shopping
+  +++ b/shopping
+  @@ -9,6 +9,6 @@
+   Suggar
+   Vinegar
+   Oil
+  -Bananos
+  +Banana
+   Pear
+   Apple
+  $ hg amend
+  abort: can not rewrite immutable changeset d85de4546133
+  [255]
+
+By default all changeset are considered "published" and can't be rewrittent.
+
+ $ hg ttlog
+
+You need to enable a mutable state in your repo the "ready" one
+
+  $ hg states ready --clever
+  $ hg ttlog
+  d85de4546133: 'adding fruit' (ready)
+  4d5dc8187023: 'adding condiment' (ready)
+  7e82d3f3c2cb: 'Monthy Python Shopping list' (published)
+
+Notice that changeset you already shared with the outside have been keep
+published.
+
+The changeset we want to rewrite is now in a mutable state.
+
+  $ hg amend
+
+A new changeset with the right diff replace the wrong one.
+
+  $ hg tlog
+  0cacb48f4482: 'adding fruit'
+  4d5dc8187023: 'adding condiment'
+  7e82d3f3c2cb: 'Monthy Python Shopping list'
+  $ hg export tip
+  # HG changeset patch
+  # User test
+  # Date 0 0
+  # Node ID 0cacb48f44828d2fd31c4e45e18fde32a5b2f07b
+  # Parent  4d5dc81870237d492284826e21840b2ca00e26d1
+  adding fruit
+  
+  diff --git a/shopping b/shopping
+  --- a/shopping
+  +++ b/shopping
+  @@ -9,3 +9,6 @@
+   Suggar
+   Vinegar
+   Oil
+  +Banana
+  +Pear
+  +Apple
+
+Getting Ride of branchy history
+----------------------------------
+
+While I was working on my list. someone help made a change remotly.
+
+close your eyes
+
+  $ cd ../remote
+  $ hg up -q
+  $ sed -i'' -e 's/Spam/Spam Spam Spam/' shopping
+  $ hg ci -m 'SPAM'
+  $ cd ../local
+
+open your eyes
+
+  $ hg pull remote
+  pulling from $TESTTMP/remote
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files (+1 heads)
+  (run 'hg heads .' to see heads, 'hg merge' to merge)
+
+I now have a new heads. Note that the remote head is immutable
+
+  $ hg ttlog
+  9ca060c80d74: 'SPAM' (published)
+  0cacb48f4482: 'adding fruit' (ready)
+  4d5dc8187023: 'adding condiment' (ready)
+  7e82d3f3c2cb: 'Monthy Python Shopping list' (published)
+  $ hg tglog -r "::(9ca060c80d74 + 0cacb48f4482)"
+  o  9ca060c80d74: 'SPAM'
+  |
+  | @  0cacb48f4482: 'adding fruit'
+  | |
+  | o  4d5dc8187023: 'adding condiment'
+  |/
+  o  7e82d3f3c2cb: 'Monthy Python Shopping list'
+  
+
+instead of merging my head with the new one. I'm going to rebase my work
+
+  $ hg diff
+  $ hg rebase -d 9ca060c80d74 -s 4d5dc8187023
+  merging shopping
+  merging shopping
+  merging shopping
+  merging shopping
+
+
+My local work is now rebase on the remote one.
+
+  $ hg kill e7a71e229632 ad97bbd3e37d # XXX fix me instead
+  $ hg ttlog
+  387187ad9bd9: 'adding fruit' (ready)
+  dfd3a2d7691e: 'adding condiment' (ready)
+  9ca060c80d74: 'SPAM' (published)
+  7e82d3f3c2cb: 'Monthy Python Shopping list' (published)
+  $ hg tglog -r '::.'
+  @  387187ad9bd9: 'adding fruit'
+  |
+  o  dfd3a2d7691e: 'adding condiment'
+  |
+  o  9ca060c80d74: 'SPAM'
+  |
+  o  7e82d3f3c2cb: 'Monthy Python Shopping list'
+  
+
+Removing changeset
+------------------------
+
+I add new item to my list
+
+  $ cat >> shopping << EOF
+  > car
+  > bus
+  > plane
+  > boat
+  > EOF
+  $ hg ci -m 'transport'
+  $ hg ttlog
+  d58c77aa15d7: 'transport' (ready)
+  387187ad9bd9: 'adding fruit' (ready)
+  dfd3a2d7691e: 'adding condiment' (ready)
+  9ca060c80d74: 'SPAM' (published)
+  7e82d3f3c2cb: 'Monthy Python Shopping list' (published)
+
+I have a new commit but I realize that don't want it. (transport shop list does
+not fit well in my standard shopping list)
+
+  $ hg kill . # . is for working directory parent.
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  working directory now at 387187ad9bd9
+
+The silly changeset is gone.
+
+  $ hg ttlog
+  387187ad9bd9: 'adding fruit' (ready)
+  dfd3a2d7691e: 'adding condiment' (ready)
+  9ca060c80d74: 'SPAM' (published)
+  7e82d3f3c2cb: 'Monthy Python Shopping list' (published)
+
+Reordering changeset
+------------------------
+
+
+We create two changeset.
+
+
+  $ cat >> shopping << EOF
+  > Shampoo
+  > Toothbrush
+  > ... More bathroom stuff to come
+  > Towel
+  > Soap
+  > EOF
+  $ hg ci -m 'bathroom stuff' -q # XXX remove the -q
+
+  $ sed -i'' -e 's/Spam/Spam Spam Spam/g' shopping
+  $ hg ci -m 'SPAM SPAM'
+  $ hg ttlog
+  c48f32fb1787: 'SPAM SPAM' (ready)
+  8d39a843582d: 'bathroom stuff' (ready)
+  387187ad9bd9: 'adding fruit' (ready)
+  dfd3a2d7691e: 'adding condiment' (ready)
+  9ca060c80d74: 'SPAM' (published)
+  7e82d3f3c2cb: 'Monthy Python Shopping list' (published)
+
+.. note: don't amend changeset 7e82d3f3c2cb or 9ca060c80d74 as they are
+immutable.
+
+I now want to push to remote all my change but the bathroom one that i'm not totally happy with yet.
+
+To be able to push "SPAM SPAM" I need a version of "SPAM SPAM" not children of "bathroom stuff"
+
+You can use rebase or relocate for that:
+
+  $ hg relocate 'p1(8d39a843582d)' --traceback
+  merging shopping
+  $ hg tglog -r '::(. + 8d39a843582d)'
+  @  02e33960e937: 'SPAM SPAM'
+  |
+  | o  8d39a843582d: 'bathroom stuff'
+  |/
+  o  387187ad9bd9: 'adding fruit'
+  |
+  o  dfd3a2d7691e: 'adding condiment'
+  |
+  o  9ca060c80d74: 'SPAM'
+  |
+  o  7e82d3f3c2cb: 'Monthy Python Shopping list'
+  
+
+We have a new SPAM SPAM version without the bathroom stuff
+
+  $ grep Spam shopping  # enouth spamm
+  Spam Spam Spam Spam Spam Spam Spam Spam Spam
+  $ grep Toothbrush shopping # no Toothbrush
+  [1]
+  $ hg export .
+  # HG changeset patch
+  # User test
+  # Date 0 0
+  # Node ID 02e33960e937ad1bd59241ebdafd7a2494240ddf
+  # Parent  387187ad9bd9d8f9a00a9fa804a26231db547429
+  SPAM SPAM
+  
+  diff --git a/shopping b/shopping
+  --- a/shopping
+  +++ b/shopping
+  @@ -1,4 +1,4 @@
+  -Spam Spam Spam
+  +Spam Spam Spam Spam Spam Spam Spam Spam Spam
+   Whizzo butter
+   Albatross
+   Rat (rather a lot)
+
+we can now push our change:
+
+  $ hg push -r . remote
+  pushing to $TESTTMP/remote
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 3 changesets with 3 changes to 1 files
+
+for simplicity shake we relocate the bathroom changeset
+
+  $ hg relocate -r 8d39a843582d 02e33960e937
+  merging shopping
+
+
+Splitting change
+------------------
+
+To be done (currently achieve with "two commit + debugobsolete")
+
+Collapsing change
+------------------
+
+To be done (currently achieve with "revert + debugobsolete" or "rebase --collapse")
+
+collaboration
+====================
+
+
+sharing mutable changeset
+----------------------------
+
+To share mutable changeset with other just check that both have the "ready"
+state activated. Otherwise you will get the previously observe behavior where
+exchanged changeset are automatically published.
+
+  $ cd ../remote
+  $ hg states 
+  published
+
+The remote repository have only the immutable "published" state activated. Any
+changeset echanged from "local" to "remote" will be set in the publised state:
+
+  $ hg -R ../local push -f remote # XXX we should pull but the support is awful
+  pushing to $TESTTMP/remote
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  $ hg ttlog
+  a3515e5d0332: 'bathroom stuff' published
+  02e33960e937: 'SPAM SPAM' published
+  387187ad9bd9: 'adding fruit' published
+  dfd3a2d7691e: 'adding condiment' published
+  9ca060c80d74: 'SPAM' published
+  7e82d3f3c2cb: 'Monthy Python Shopping list' published
+
+
+
+We do not want to publish the "bathroom changeset". Let's rollback the last transaction
+
+  $ hg rollback
+  repository tip rolled back to revision 4 (undo push)
+  working directory now based on revision 1
+  $ hg ttlog
+  02e33960e937: 'SPAM SPAM' published
+  387187ad9bd9: 'adding fruit' published
+  dfd3a2d7691e: 'adding condiment' published
+  9ca060c80d74: 'SPAM' published
+  7e82d3f3c2cb: 'Monthy Python Shopping list' published
+  $ rm ../local/.hg/states/published-heads     # XXX USE --exact
+  $ hg -R ../local publish 02e33960e937 # XXX FIX THE BUG
+
+To enable the mutable "ready" state in a repository, use the states command.
+
+  $ hg states ready
+  $ hg states 
+  published
+  ready
+
+I can nom exchange mutable changeset between "remote" and "local" repository.
+
+  $ hg pull local # XXX We pull too much stuff
+  pulling from $TESTTMP/local
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 10 changesets with 10 changes to 1 files (+5 heads)
+  (run 'hg heads' to see heads, 'hg merge' to merge)
+  $ hg ttlog
+  a3515e5d0332: 'bathroom stuff' ready
+  02e33960e937: 'SPAM SPAM' published
+  387187ad9bd9: 'adding fruit' published
+  dfd3a2d7691e: 'adding condiment' published
+  9ca060c80d74: 'SPAM' published
+  7e82d3f3c2cb: 'Monthy Python Shopping list' published
+
+Rebasing out-of-sync change after update
+----------------------------------------------
+
+Remotely someone add a new changeset on top of our mutable "bathroom" on.
+
+  $ hg up a3515e5d0332 -q
+  $ cat >> shopping << EOF
+  > Giraffe
+  > Rhino
+  > Lion
+  > Bear
+  > EOF
+  $ hg ci -m 'animals' -q # XXX remove the -q
+
+While this time locally, we rebase the updated the "bathroom changeset"
+
+  $ cd ../local
+  $ hg up a3515e5d0332 -q
+  $ sed -i'' -e 's/... More bathroom stuff to come/Bath Robe/' shopping
+  $ hg amend
+  $ hg tlog
+  962d3a7d27ad: 'bathroom stuff'
+  02e33960e937: 'SPAM SPAM'
+  387187ad9bd9: 'adding fruit'
+  dfd3a2d7691e: 'adding condiment'
+  9ca060c80d74: 'SPAM'
+  7e82d3f3c2cb: 'Monthy Python Shopping list'
+
+
+When we pull from remote again we get an unstable state!
+
+  $ hg pull remote
+  pulling from $TESTTMP/remote
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files (+1 heads)
+  (run 'hg heads .' to see heads, 'hg merge' to merge)
+  $ hg tlog
+  0b061760b677: 'animals'
+  962d3a7d27ad: 'bathroom stuff'
+  a3515e5d0332: 'bathroom stuff'
+  02e33960e937: 'SPAM SPAM'
+  387187ad9bd9: 'adding fruit'
+  dfd3a2d7691e: 'adding condiment'
+  9ca060c80d74: 'SPAM'
+  7e82d3f3c2cb: 'Monthy Python Shopping list'
+
+The new changeset "animal" is based one an old changeset of "bathroom". You can
+see both version showing up the log.
+
+  $ hg tglog -r '::(962d3a7d27ad + 0b061760b677)'
+  o  0b061760b677: 'animals'
+  |
+  | @  962d3a7d27ad: 'bathroom stuff'
+  | |
+  o |  a3515e5d0332: 'bathroom stuff'
+  |/
+  o  02e33960e937: 'SPAM SPAM'
+  |
+  o  387187ad9bd9: 'adding fruit'
+  |
+  o  dfd3a2d7691e: 'adding condiment'
+  |
+  o  9ca060c80d74: 'SPAM'
+  |
+  o  7e82d3f3c2cb: 'Monthy Python Shopping list'
+  
+
+In hgviewn there is a nice doted relation highlighting 962d3a7d27ad  is a new
+version of a3515e5d0332. this is not yet ported to graphlog.
+
+To resolve this unstable state, you need to relocate 0b061760b677 onto
+962d3a7d27ad the "hg evolve" will make the thinking for you and suggest it to
+you.
+
+  $ hg evolve
+  hg relocate --rev 0b061760b677 962d3a7d27ad
+
+Let's do it
+
+  $ hg relocate --rev 0b061760b677 962d3a7d27ad
+  merging shopping
+
+The old vesion of bathroom is hidden again now.
+
+  $ hg tlog
+  39a85a192689: 'animals'
+  962d3a7d27ad: 'bathroom stuff'
+  02e33960e937: 'SPAM SPAM'
+  387187ad9bd9: 'adding fruit'
+  dfd3a2d7691e: 'adding condiment'
+  9ca060c80d74: 'SPAM'
+  7e82d3f3c2cb: 'Monthy Python Shopping list'
+
+We can push this evolution to remote
+
+  $ hg push -f remote # XXX should not require -f
+  pushing to $TESTTMP/remote
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 1 files (+1 heads)
+
+remote get a warning that current working directory is based on an obsolete changeset
+
+  $ cd ../remote
+  $ hg up . # XXX "loulz"
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  Working directory parent is obsolete
+
+  $ hg up 39a85a192689
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+Relocating out-of-sync change after kill
+----------------------------------------------
+
+The remote guy keep working
+
+  $ sed -i'' -e 's/Spam/Spam Spam Spam Spam/g' shopping
+  $ hg commit -m "SPAM SPAM SPAM"
+
+Work I can keep getting localy
+
+  $ cd ../local
+  $ hg pull remote
+  pulling from $TESTTMP/remote
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  (run 'hg update' to get a working copy)
+  $ hg tlog
+  e768beeb835c: 'SPAM SPAM SPAM'
+  39a85a192689: 'animals'
+  962d3a7d27ad: 'bathroom stuff'
+  02e33960e937: 'SPAM SPAM'
+  387187ad9bd9: 'adding fruit'
+  dfd3a2d7691e: 'adding condiment'
+  9ca060c80d74: 'SPAM'
+  7e82d3f3c2cb: 'Monthy Python Shopping list'
+
+In the mean time I noticed you can't buy animals in a super market and I kill the animal changeset:
+
+  $ hg kill 39a85a192689 # issue warning here
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  working directory now at 962d3a7d27ad
+
+The animals changeset is still displayed because the "SPAM SPAM SPAM" changeset
+is neither dead or obsolete.  My repository is in an unstable state again.
+
+  $ hg tlog 
+  e768beeb835c: 'SPAM SPAM SPAM'
+  39a85a192689: 'animals'
+  962d3a7d27ad: 'bathroom stuff'
+  02e33960e937: 'SPAM SPAM'
+  387187ad9bd9: 'adding fruit'
+  dfd3a2d7691e: 'adding condiment'
+  9ca060c80d74: 'SPAM'
+  7e82d3f3c2cb: 'Monthy Python Shopping list'
+  $ hg tglog  -r '::e768beeb835c'
+  o  e768beeb835c: 'SPAM SPAM SPAM'
+  |
+  o  39a85a192689: 'animals'
+  |
+  @  962d3a7d27ad: 'bathroom stuff'
+  |
+  o  02e33960e937: 'SPAM SPAM'
+  |
+  o  387187ad9bd9: 'adding fruit'
+  |
+  o  dfd3a2d7691e: 'adding condiment'
+  |
+  o  9ca060c80d74: 'SPAM'
+  |
+  o  7e82d3f3c2cb: 'Monthy Python Shopping list'
+  
+
+#  $ hg evolve # XXX not ready yet
+#  hg relocate --rev  e768beeb835c 962d3a7d27ad
+
+  $ hg relocate -r  e768beeb835c 'p1(39a85a192689)'
+  merging shopping
+
+  $ hg tlog 
+  19098f8178f3: 'SPAM SPAM SPAM'
+  962d3a7d27ad: 'bathroom stuff'
+  02e33960e937: 'SPAM SPAM'
+  387187ad9bd9: 'adding fruit'
+  dfd3a2d7691e: 'adding condiment'
+  9ca060c80d74: 'SPAM'
+  7e82d3f3c2cb: 'Monthy Python Shopping list'
+
+Handling Conflicting amend
+----------------------------------------------
+
+We can detect that multiple diverging//conflicting amend have been made. There
+will be a "evol-merge" command to merge conflicting amend