Commits

Benoît Allard committed 6d39516 Merge

merged

Comments (0)

Files changed (10)

docs/evolve-faq.rst

File contents unchanged.

docs/from-mq.rst

File contents unchanged.
 Here are various Materials on planned improvement to mercurial regarding
 rewriting history.
 
-The effort  splits in two parts:
+First read about what challenge arise while rewriting history and how we plan to
+solve them once and for all.
+
+.. toctree::
+   :maxdepth: 2
+
+   unstability
+
+The effort is splits in two parts:
 
  * The **obsolete marker** concept aims to provide and alternative to ``strip``
-   to get ride of changesets.
+   to get rid of changesets.
 
  * The **evolve** mercurial extension to rewrite history using *obsolete marker*
    under the hood.
 
-
 The first and most important step is by far the **obsolete marker**. However
-most user will never be directly exposed to the concept. For this reason
-document about changeset evolution are put first.
-
+most users will never be directly exposed to the concept. For this reason
+this manual starts with changeset evolution.
 
 Evolve: A robust alternative to MQ
 ====================================
 
-Evolve is an experimental history rewriting extensions that use obsolete
-markers. It is inspired from MQ and pbranch but have multiple advantage over
+Evolve is an experimental history rewriting extension that uses obsolete
+markers. It is inspired from MQ and pbranch but have multiple advantages over
 them:
 
-* sticks to "Work where you are" philosophy (I'll need better wording
-  for that)
+* Focus on your current work.
+
+    You can focus your work on a single changeset and take care of adapting
+    descendent changeset later.
 
 * Handle **non-linear history with branches and merges**
 
-* Use **robust merge** mechanism of mercurial.
+* Rely internally on **robust merge** mechanism of mercurial.
 
-  simple conflict are handled by real merge tools using appropriate ancestor.
+  Simple conflict are handled by real merge tools using appropriate ancestor.
   Conflict are much rarer and much more user friendly.
 
 *  Mutable history **fully available all the time**.
 
-  You are do not need to unapply and apply patche to access various part of you
-  history.
+  always use 'hg update' and forget about (un)applying patches to access the
+  mutable part of your history.
 
-* Use **plain changeset** only. Evole create and exchange real changeset only. 
-  Mutable history can be used in all usual operation 'pull, push, log, diff …)
 
-* Allow **sharing and collaboration** mutable history without fear of duplicate.
+* Use only **plain changeset** and forget about patches. Evole will create and
+  exchange real changesets. Mutable history can be used in all usual operations:
+  pull, push, log, diff, etc.
+
+* Allow **sharing and collaboration** mutable history without fear of duplicate
   (thanks to obsolete marker).
 
 * Cover all mq usage but guard.
 
 .. warning:: The evolve extention and the obsolete marker are at an experimental
-            stage. While using obsolet you'll likely be exposed to complexe
+            stage. While using obsolete you'll likely be exposed to complex
             implication of the **obsolete marker** concept. I do not recommend
-            non power user to test this at this stage.
+            non-power user to test this at this stage.
+
+            XXX make sure to read the XXX section before using it.
 
             Production ready version should hide such details to normal user.
 
     $ hg clone http://hg-dev.octopoid.net/hgwebdir.cgi/mutable-history/
     $ mutable-history/enable.sh >> ~/.hgrc
 
-You will probably want to use the associated version of hgview (QT viewer
-only). ::
+You will probably want to use the associated version of hgview (qt viewer
+recommended). ::
 
     $ hg clone http://hg-dev.octopoid.net/hgwebdir.cgi/hgview/
     $ cd hgview
     $ python setup.py install --user
 
+works with mercurial 2.1 and 2.2 (recommended)
 
  ---
 
-For more information see documents below
+For more information see documents below:
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
-   tutorial
+   tutorials/tutorial
    evolve-faq
    from-mq
    evolve-collaboration
 
 - Very fast history rewriting operations,
 
-- auditable and reversible history rewritting process,
+- auditable and reversible history rewriting process,
 
 - clean final history,
 
-- share and collaborate on mutable part of the history,
+- share and collaborate on mutable parts of the history,
 
-- gracefully handle history rewriting conflict,
+- gracefully handle history rewriting conflicts,
 
-- allows various history rewriting UI to collaborate with a underlying common API.
+- allow various history rewriting UI to collaborate with a underlying common API.
 
  ---
 
 For more information see documents below
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
    obs-concept
    obs-implementation
 
 
+Known caveats
+=============
 
+Here is a list of known issues that will be fixed later:
 
+* Unstable changeset turn secret.
 
+* ``hg stabilize`` does not handle conflicts.
 
-Know canveas
+Known limitation and bug
 =================================
 
 Here is a list of know issue that will be fixed later:
 
-* Unstable changeset turns secret.
 
-* ``hg stabilize`` does not handle conflict.
 
-* Mercurial think you are pushing additional heads even when the new head
-  obsolete another one. You have to use hg push -f more than necessary.
+* ``hg stabilize`` does not handle merge conflict.
+
+    You must fallback to graft or rebase when that happen.
+
+* rewriting conflict are not detected yet``hg stabilize`` does not handle them.
 
 * ``hg update`` can move an obsolete parent
 
-* you need to provideto graft --continue -O if you started you graft using -O.
+* you need to provide to `graft --continue -O` if you started you graft using `-O`.
+
+* ``hg merge`` considers an extinct head to be a valid target, hence requiring
+  you to manually specify target all the time.
+
+* trying to exchange obsolete relations with a static http repo will crash.
+
+* Extinct changeset are turned secret by various commands.
+
+* Extinct changesets are hidden using the *hidden* feature of mercurial only
+  supported by a few commands.
+
+  Only ``hg log``, ``hgview`` and `hg glog` (2.2 only) support it. ``hg head`` or other visual viewer don't.
+
+* hg heads show extinct changeset
+
+Fixed in 2.2
+---------------------------------
 
 * hg graphlog show extinct changeset
 
-* hg heads show extinct changeset
+* Mercurial 2.1 think you are pushing additional heads even when the new head
+  obsolete another one. You have to use hg push -f more often than necessary.
 
-* hg merge considered extinct head as valid target. requiring you to manually
-  specify target all the time.
 
-* obsolete relation exchange crash (as in traceback) on static http repo.
+* ``hg heads`` shows extinct changeset
 
+* ``hg merge`` considers an extinct head to be a valid target, hence requiring
+  you to manually specify target all the time.
 
-
-
+* trying to exchange obsolete relations with a static http repo will crash.
 
 Annexe
-=================================
+======
 
 .. toctree::
    :maxdepth: 1

docs/obs-concept.rst

File contents unchanged.

docs/obs-implementation.rst

File contents unchanged.

docs/tutorials/tutorial.t

-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
+Initial setup
 ---------------------
-
-
-First there is some setup phase you will understand later.
-
-there is a local repository and a remote one.
-
+.. Various setup
 
   $ cat >> $HGRCPATH << EOF
   > [ui]
   > amend = amend -d '0 0'
   > [extensions]
   > hgext.graphlog=
-  > hgext.rebase=
   > EOF
-  $ $(dirname $TESTDIR)/enable.sh >> $HGRCPATH 2> /dev/null
 
   $ hg init local
   $ cat >> local/.hg/hgrc << EOF
   > [paths]
   > remote = ../remote
+  > other = ../other
   > [ui]
   > user = Babar the King
   > EOF
   > user = Celestine the Queen
   > EOF
 
+  $ hg init other
+  $ cat >> other/.hg/hgrc << EOF
+  > [ui]
+  > user = Princess Flore
+  > EOF
+
+
+This tutorial use the following configuration for Mercurial:
+
+A compact log template with phase data:
+
+  $ hg showconfig ui
+  ui.slash=True
+  ui.logtemplate="{node|short} ({phase}): {desc}\n"
+
+Improved git format diff:
+
+  $ hg showconfig diff
+  diff.git=1
+
+And the graphlog extension
+  $ hg showconfig extensions
+  extensions.hgext.graphlog=
+
+And of course, we anabled the experimental extensions for mutable history:
+
+  $ $(dirname $TESTDIR)/enable.sh >> $HGRCPATH 2> /dev/null
+
+
+-----------------------
+Single Developer Usage
+-----------------------
+
+This tutorial shows how to use evolution to rewrite history locally.
+
+
+Fixing mistake with `hg amend`
+--------------------------------
+
+We are versionning a shopping list
+
   $ cd local
-
-You can reopen you eyes.
-
-Now we make a first version of our shopping list.
-
   $ cat  >> shopping << EOF
   > Spam
   > Whizzo butter
   $ hg commit -A -m "Monthy Python Shopping list"
   adding shopping
 
-We share this first version with the outside.
+Its first version is shared with the outside.
 
   $ hg push remote
   pushing to $TESTTMP/remote
   > EOF
   $ hg commit -m "adding fruit"
 
-I now have the following history:
+This history is very linear
 
-  $ hg log
-  d85de4546133 (draft): adding fruit
-  4d5dc8187023 (draft): adding condiment
-  7e82d3f3c2cb (public): Monthy Python Shopping list
+  $ hg glog
+  @  d85de4546133 (draft): adding fruit
+  |
+  o  4d5dc8187023 (draft): adding condiment
+  |
+  o  7e82d3f3c2cb (public): Monthy Python Shopping list
+  
 
-But, I just notice, I made a typo in Banana.
+But a typo was made in Babanas!
 
   $ hg export tip
   # HG changeset patch
   +Pear
   +Apple
 
-The faulty changeset is in the "draft" phase because he was not exchanged with the outside. The first one have been exchanged and is an immutable public changeset
+The faulty changeset is in the "draft" phase because he was not exchanged with
+the outside. The first one have been exchanged and is an immutable public
+changeset.
 
-  $ hg log
-  d85de4546133 (draft): adding fruit
-  4d5dc8187023 (draft): adding condiment
-  7e82d3f3c2cb (public): Monthy Python Shopping list
+  $ hg glog
+  @  d85de4546133 (draft): adding fruit
+  |
+  o  4d5dc8187023 (draft): adding condiment
+  |
+  o  7e82d3f3c2cb (public): Monthy Python Shopping list
+  
 
 hopefully. I can use hg amend to rewrite my faulty changeset!
 
 
 A new changeset with the right diff replace the wrong one.
 
-  $ hg log
-  0cacb48f4482 (draft): adding fruit
-  4d5dc8187023 (draft): adding condiment
-  7e82d3f3c2cb (public): Monthy Python Shopping list
+  $ hg glog
+  @  0cacb48f4482 (draft): adding fruit
+  |
+  o  4d5dc8187023 (draft): adding condiment
+  |
+  o  7e82d3f3c2cb (public): Monthy Python Shopping list
+  
   $ hg export tip
   # HG changeset patch
   # User test
 
 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
+I'll get this remote changeset when pulling
 
   $ hg pull remote
   pulling from $TESTTMP/remote
   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
+I now have a new heads. Note that this remote head is immutable
 
-  $ hg log
-  9ca060c80d74 (public): SPAM
-  0cacb48f4482 (draft): adding fruit
-  4d5dc8187023 (draft): adding condiment
-  7e82d3f3c2cb (public): Monthy Python Shopping list
   $ hg log -G
   o  9ca060c80d74 (public): SPAM
   |
 
 My local work is now rebased on the remote one.
 
-  $ hg log
-  387187ad9bd9 (draft): adding fruit
-  dfd3a2d7691e (draft): adding condiment
-  9ca060c80d74 (public): SPAM
-  7e82d3f3c2cb (public): Monthy Python Shopping list
   $ hg log -G
   @  387187ad9bd9 (draft): adding fruit
   |
   > boat
   > EOF
   $ hg ci -m 'transport'
-  $ hg log
-  d58c77aa15d7 (draft): transport
-  387187ad9bd9 (draft): adding fruit
-  dfd3a2d7691e (draft): adding condiment
-  9ca060c80d74 (public): SPAM
-  7e82d3f3c2cb (public): Monthy Python Shopping list
+  $ hg log -G
+  @  d58c77aa15d7 (draft): transport
+  |
+  o  387187ad9bd9 (draft): adding fruit
+  |
+  o  dfd3a2d7691e (draft): adding condiment
+  |
+  o  9ca060c80d74 (public): SPAM
+  |
+  o  7e82d3f3c2cb (public): Monthy Python Shopping list
+  
 
 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.
+  $ 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 log
-  387187ad9bd9 (draft): adding fruit
-  dfd3a2d7691e (draft): adding condiment
-  9ca060c80d74 (public): SPAM
-  7e82d3f3c2cb (public): Monthy Python Shopping list
+  $ hg log -G
+  @  387187ad9bd9 (draft): adding fruit
+  |
+  o  dfd3a2d7691e (draft): adding condiment
+  |
+  o  9ca060c80d74 (public): SPAM
+  |
+  o  7e82d3f3c2cb (public): Monthy Python Shopping list
+  
 
 Reordering changeset
 ------------------------
 
 
-We create two changeset.
+We create two changesets.
 
 
   $ cat >> shopping << EOF
 
   $ sed -i'' -e 's/Spam/Spam Spam Spam/g' shopping
   $ hg ci -m 'SPAM SPAM'
-  $ hg log
-  c48f32fb1787 (draft): SPAM SPAM
-  8d39a843582d (draft): bathroom stuff
-  387187ad9bd9 (draft): adding fruit
-  dfd3a2d7691e (draft): adding condiment
-  9ca060c80d74 (public): SPAM
-  7e82d3f3c2cb (public): Monthy Python Shopping list
+  $ hg log -G
+  @  c48f32fb1787 (draft): SPAM SPAM
+  |
+  o  8d39a843582d (draft): bathroom stuff
+  |
+  o  387187ad9bd9 (draft): adding fruit
+  |
+  o  dfd3a2d7691e (draft): adding condiment
+  |
+  o  9ca060c80d74 (public): SPAM
+  |
+  o  7e82d3f3c2cb (public): Monthy Python Shopping list
+  
 
 .. 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"
+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 -r' or 'graft -O' for that:
 
 
 We have a new SPAM SPAM version without the bathroom stuff
 
-  $ grep Spam shopping  # enouth spamm
+  $ grep Spam shopping  # enouth spam
   Spam Spam Spam Spam Spam Spam Spam Spam Spam
   $ grep Toothbrush shopping # no Toothbrush
   [1]
   $ hg rebase -Dr 8d39a843582d -d a2fccc2e7b08
   merging shopping
   $ hg phase --draft .
+  $ hg log -G
+  @  8a79ae8b029e (draft): bathroom stuff
+  |
+  o  a2fccc2e7b08 (public): SPAM SPAM
+  |
+  o  387187ad9bd9 (public): adding fruit
+  |
+  o  dfd3a2d7691e (public): adding condiment
+  |
+  o  9ca060c80d74 (public): SPAM
+  |
+  o  7e82d3f3c2cb (public): Monthy Python Shopping list
+  
+
 
 
 Splitting change
 
 To be done (currently achieve with "revert + debugobsolete" or "rebase --collapse")
 
-collaboration
-====================
+
+
+
+
+
+-----------------------
+Collaboration
+-----------------------
 
 
 sharing mutable changeset
   $ cd ../remote
   $ hg -R ../local/ showconfig phases
 
-the localrepo does not have any specific configuration for `phases.publish`. It is ``true`` by default.
+the localrepo does not have any specific configuration for `phases.publish`. It
+is ``true`` by default.
 
   $ hg pull local
   pulling from $TESTTMP/local
   adding file changes
   added 1 changesets with 1 changes to 1 files
   (run 'hg update' to get a working copy)
-  $ hg log
-  8a79ae8b029e (public): bathroom stuff
-  a2fccc2e7b08 (public): SPAM SPAM
-  387187ad9bd9 (public): adding fruit
-  dfd3a2d7691e (public): adding condiment
-  9ca060c80d74 (public): SPAM
-  7e82d3f3c2cb (public): Monthy Python Shopping list
+  $ hg log -G
+  o  8a79ae8b029e (public): bathroom stuff
+  |
+  o  a2fccc2e7b08 (public): SPAM SPAM
+  |
+  o  387187ad9bd9 (public): adding fruit
+  |
+  o  dfd3a2d7691e (public): adding condiment
+  |
+  @  9ca060c80d74 (public): SPAM
+  |
+  o  7e82d3f3c2cb (public): Monthy Python Shopping list
+  
 
 
 
 
   $ hg rollback
   repository tip rolled back to revision 4 (undo pull)
-  $ hg log
-  a2fccc2e7b08 (public): SPAM SPAM
-  387187ad9bd9 (public): adding fruit
-  dfd3a2d7691e (public): adding condiment
-  9ca060c80d74 (public): SPAM
-  7e82d3f3c2cb (public): Monthy Python Shopping list
+  $ hg log -G
+  o  a2fccc2e7b08 (public): SPAM SPAM
+  |
+  o  387187ad9bd9 (public): adding fruit
+  |
+  o  dfd3a2d7691e (public): adding condiment
+  |
+  @  9ca060c80d74 (public): SPAM
+  |
+  o  7e82d3f3c2cb (public): Monthy Python Shopping list
+  
 
-Let's make thz local repo "non publishing"
+Let's make the local repo "non publishing"
 
   $ echo "[phases]\npublish=false" >> ../local/.hg/hgrc
   $ echo "[phases]\npublish=false" >> .hg/hgrc
   adding file changes
   added 1 changesets with 1 changes to 1 files
   (run 'hg update' to get a working copy)
-  $ hg log
-  8a79ae8b029e (draft): bathroom stuff
-  a2fccc2e7b08 (public): SPAM SPAM
-  387187ad9bd9 (public): adding fruit
-  dfd3a2d7691e (public): adding condiment
-  9ca060c80d74 (public): SPAM
-  7e82d3f3c2cb (public): Monthy Python Shopping list
+  $ hg log -G
+  o  8a79ae8b029e (draft): bathroom stuff
+  |
+  o  a2fccc2e7b08 (public): SPAM SPAM
+  |
+  o  387187ad9bd9 (public): adding fruit
+  |
+  o  dfd3a2d7691e (public): adding condiment
+  |
+  @  9ca060c80d74 (public): SPAM
+  |
+  o  7e82d3f3c2cb (public): Monthy Python Shopping list
+  
 
 Rebasing unstable change after pull
 ----------------------------------------------
 
-Remotely someone add a new changeset on top of our mutable "bathroom" on.
+Remotely someone add a new changeset on top of the mutable "bathroom" on.
 
   $ hg up 8a79ae8b029e -q
   $ cat >> shopping << EOF
   > Lion
   > Bear
   > EOF
-  $ hg ci -m 'animals' -q # XXX remove the -q
+  $ hg ci -m 'animals'
 
-While this time locally, we updated "bathroom changeset"
+But at the same time, locally, this same "bathroom changeset" was updated.
 
   $ cd ../local
   $ hg up 8a79ae8b029e -q
   $ sed -i'' -e 's/... More bathroom stuff to come/Bath Robe/' shopping
   $ hg amend
-  $ hg log
-  ffa278c50818 (draft): bathroom stuff
-  a2fccc2e7b08 (public): SPAM SPAM
-  387187ad9bd9 (public): adding fruit
-  dfd3a2d7691e (public): adding condiment
-  9ca060c80d74 (public): SPAM
-  7e82d3f3c2cb (public): Monthy Python Shopping list
+  $ hg log -G
+  @  ffa278c50818 (draft): bathroom stuff
+  |
+  o  a2fccc2e7b08 (public): SPAM SPAM
+  |
+  o  387187ad9bd9 (public): adding fruit
+  |
+  o  dfd3a2d7691e (public): adding condiment
+  |
+  o  9ca060c80d74 (public): SPAM
+  |
+  o  7e82d3f3c2cb (public): Monthy Python Shopping list
+  
 
 
 When we pull from remote again we get an unstable state!
   added 1 changesets with 1 changes to 1 files (+1 heads)
   (run 'hg heads .' to see heads, 'hg merge' to merge)
   1 new unstables changesets
-  $ hg log -r 'extinct()'
-  $ hg log
-  9ac5d0e790a2 (draft): animals
-  ffa278c50818 (draft): bathroom stuff
-  8a79ae8b029e (draft): bathroom stuff
-  a2fccc2e7b08 (public): SPAM SPAM
-  387187ad9bd9 (public): adding fruit
-  dfd3a2d7691e (public): adding condiment
-  9ca060c80d74 (public): SPAM
-  7e82d3f3c2cb (public): 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.
+see both version showing up in the log.
 
-  $ hg glog
+  $ hg log -G
   o  9ac5d0e790a2 (draft): animals
   |
   | @  ffa278c50818 (draft): bathroom stuff
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-In hgview there is a nice doted relation highlighting ffa278c50818  is a new
-version of 8a79ae8b029e. this is not yet ported to graphlog.
+The older version 8a79ae8b029e never ceased to exist in the local repo. It was
+jsut hidden and excluded from pull and push.
+
+.. note:: In hgview there is a nice doted relation highlighting ffa278c50818  as a new version of 8a79ae8b029e. this is not yet ported to graphlog.
+
+Their is **unstable** changeset in this history now. Mercurial will refuse to
+share it with the outside:
+
+  $ hg push other
+  pushing to $TESTTMP/other
+  searching for changes
+  abort: Trying to push unstable changeset: 9ac5d0e790a2!
+  (use 'hg stabilize' to get a stable history (or --force to proceed))
+  [255]
+ 
+
+
 
 To resolve this unstable state, you need to rebase 9ac5d0e790a2 onto
-ffa278c50818 the "hg stabilize" command will make this for you. It has a
---dry-run option to only suggest the next move
+ffa278c50818 the "hg stabilize" command will make this for you.
+
+It has a --dry-run option to only suggest the next move.
 
   $ hg stabilize --dry-run
   move:[15] animals
   atop:[14] bathroom stuff
   hg rebase -Dr 9ac5d0e790a2 -d ffa278c50818
 
-
 Let's do it
 
   $ hg rebase -Dr 9ac5d0e790a2 -d ffa278c50818
   merging shopping
 
-The old version of bathroom is hidden again now.
+The old version of bathroom is hidden again.
 
-  $ hg log
-  437efbcaf700 (draft): animals
-  ffa278c50818 (draft): bathroom stuff
-  a2fccc2e7b08 (public): SPAM SPAM
-  387187ad9bd9 (public): adding fruit
-  dfd3a2d7691e (public): adding condiment
-  9ca060c80d74 (public): SPAM
-  7e82d3f3c2cb (public): Monthy Python Shopping list
+  $ hg log -G
+  @  437efbcaf700 (draft): animals
+  |
+  o  ffa278c50818 (draft): bathroom stuff
+  |
+  o  a2fccc2e7b08 (public): SPAM SPAM
+  |
+  o  387187ad9bd9 (public): adding fruit
+  |
+  o  dfd3a2d7691e (public): adding condiment
+  |
+  o  9ca060c80d74 (public): SPAM
+  |
+  o  7e82d3f3c2cb (public): Monthy Python Shopping list
+  
 
 
 We can push this evolution to remote
 
-  $ hg push -f remote # XXX should not require -f
+  $ hg push remote
   pushing to $TESTTMP/remote
   searching for changes
   adding changesets
 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
+  $ hg pull local # we up again to trigger the warning. it was displayed during the push
+  pulling from $TESTTMP/local
+  searching for changes
+  no changes found
   Working directory parent is obsolete
 
   $ hg up 437efbcaf700
   $ sed -i'' -e 's/Spam/Spam Spam Spam Spam/g' shopping
   $ hg commit -m "SPAM SPAM SPAM"
 
-Work I can keep getting localy
+I'm pulling its work locally.
 
   $ cd ../local
   $ hg pull remote
   adding file changes
   added 1 changesets with 1 changes to 1 files
   (run 'hg update' to get a working copy)
-  $ hg log
-  ae45c0c3092a (draft): SPAM SPAM SPAM
-  437efbcaf700 (draft): animals
-  ffa278c50818 (draft): bathroom stuff
-  a2fccc2e7b08 (public): SPAM SPAM
-  387187ad9bd9 (public): adding fruit
-  dfd3a2d7691e (public): adding condiment
-  9ca060c80d74 (public): SPAM
-  7e82d3f3c2cb (public): Monthy Python Shopping list
+  $ hg log -G
+  o  ae45c0c3092a (draft): SPAM SPAM SPAM
+  |
+  @  437efbcaf700 (draft): animals
+  |
+  o  ffa278c50818 (draft): bathroom stuff
+  |
+  o  a2fccc2e7b08 (public): SPAM SPAM
+  |
+  o  387187ad9bd9 (public): adding fruit
+  |
+  o  dfd3a2d7691e (public): adding condiment
+  |
+  o  9ca060c80d74 (public): SPAM
+  |
+  o  7e82d3f3c2cb (public): 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:
 
 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 log
-  ae45c0c3092a (draft): SPAM SPAM SPAM
-  437efbcaf700 (draft): animals
-  ffa278c50818 (draft): bathroom stuff
-  a2fccc2e7b08 (public): SPAM SPAM
-  387187ad9bd9 (public): adding fruit
-  dfd3a2d7691e (public): adding condiment
-  9ca060c80d74 (public): SPAM
-  7e82d3f3c2cb (public): Monthy Python Shopping list
-
-  $ hg log -r 'unstable()'
-  ae45c0c3092a (draft): SPAM SPAM SPAM
-
   $ hg log -G
   o  ae45c0c3092a (draft): SPAM SPAM SPAM
   |
   |
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
-# XXX make this work
+
+  $ hg log -r 'unstable()'
+  ae45c0c3092a (draft): SPAM SPAM SPAM
+
+# XXX make kill stabilization works
 #  $ hg stabilize --any
 #  merging shopping
 
   grafting revision 17
   merging shopping
 
-  $ hg log
-  20de1fb1cec5 (draft): SPAM SPAM SPAM
-  ffa278c50818 (draft): bathroom stuff
-  a2fccc2e7b08 (public): SPAM SPAM
-  387187ad9bd9 (public): adding fruit
-  dfd3a2d7691e (public): adding condiment
-  9ca060c80d74 (public): SPAM
-  7e82d3f3c2cb (public): Monthy Python Shopping list
+  $ hg log -G
+  @  20de1fb1cec5 (draft): SPAM SPAM SPAM
+  |
+  o  ffa278c50818 (draft): bathroom stuff
+  |
+  o  a2fccc2e7b08 (public): SPAM SPAM
+  |
+  o  387187ad9bd9 (public): adding fruit
+  |
+  o  dfd3a2d7691e (public): adding condiment
+  |
+  o  9ca060c80d74 (public): SPAM
+  |
+  o  7e82d3f3c2cb (public): 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
+
+This command is not ready yet.

docs/unstability.rst

+
 -----------------------------------
-The Unstability Principle
+The instability Principle
 -----------------------------------
 
 
 An intrinsic contradiction
 -----------------------------------
 
+XXX starts by talking about getting ride of changeset.
 
 DVCS bring two new major concepts to the Version Control Scene:
 
-    * Organisation of the history with robust DAG,
-    * Mutation of history.
+    * History is organized as a robust DAG,
+    * History can be rewritten.
 
 
-However, the two concepts opposes them self:
+However, the two concepts are in contradiction:
 
 To achieve a robust history, three key elements are gathered in *changeset*:
 
     * Reference to the previous full snapshot used to build the new one,
     * A description of the change who lead from the old content to the new old.
 
-All three elements are used generate a *unique* hash that identify the changeset
+All three elements are to compute a *unique* hash that identify the changeset
 (with various other metadata). This identification is a key part of DVCS design.
 
+This is a very useful property because Changing B parent means changing B
+content too.  This require the creation of **another** changeset which is a good
+semantic.
+
 ::
 
   Schema base,  A, B and B'
 
-The old changeset is usually discarded
-t in DVCS history.
+To avoid duplication, the older changeset is usually discarded from accessible
+history. I'm calling them *obsolete* changesets.
 
 
+But rewriting a changeset with children does not changes children parent! And
+because children of the rewritten changeset still **depends** on the older
+"dead" version of the changeset with can not get ride of this dead version.
+
 ::
 
   Schema base,  A and A' and B.
 
-Rewriting a changeset with children does not changes children parent! And
-because children of the rewritten changeset still **depends** on the older
-"dead" version of the changeset with can not get ride of this dead version.
-
-This is a very useful property because Changing B parent means changing B
-content too.  This require the creation of **another** changeset.
-
-I'll qualify those children as **unstable** because they are based one a dead
+I'm calling those children **unstable** because they are based one a dead
 changeset and prevent people to get ride of it.
 
 This instability is an **unavoidable consequence** of the strict dependency of
-changese.  History Rewriting history alway  need to take it in account and
+changeset.  History Rewriting history alway  need to take it in account and
 provide a way to rewrite the descendant on the new changeset to avoid
 coexistence of the old and new version of a rewritten changeset..
 
 Everybody is working around the issue
 ------------------------------------------------
 
-I'm not claiming that rewriting history is impossible. People are 
-
+I'm not claiming that rewriting history is impossible. People are successfully
+doing for years. However they all need to work around *instability*. Several
+work around strategy exists.
 
 
 Rewriting all at once
 ``````````````````````````
 
+The simplest way to avoid instability is to ensure rewriting operation always
+ends in a stable situation. This is achieve by rewriting all impacted changeset
+at the same time.
 
+Rewriting all descendants at the same time than the rewritted of a changeset.
 
-stable situation to stable situation
+::
 
-Distributed means that you do not control what happen outside your repository:
+  Schema!
 
+Several Mercurial commands apply it: rebase, collapse, histedit.  Mercurial also
+refuse to amend changeset with descendant.  The git branch design enforce such
+approach in git too.
 
-* phase.
-* overwrite.
 
+However, DVCS are **Distributed**. This means that you do not control what
+happen outside your repository. Once a changeset have been exchanged *outside*,
+there is no way to be sure it does not have descendants somewhere else.
+Therefore **if you rewrite changeset that exists elsewhere, you can't eradicate
+the risk of instability.**
 
-Boiler Plate
+Do not rewrite exchanged changeset
+```````````````````````````````````
+
+To work around the issue above, mercurial introduced phases that prevent you to
+rewrite shared changeset and ensure other can't pull certain changeset from you.
+But this is a very frustrating limitation that prevent you to efficiently share,
+review and collaborate on mutable changeset.
+
+Git world use another approach to prevent instability.  By convention only a
+single developper works on a changeset contained in a named branch. But once
+again this is a huge blocker for collaborating. Moreover clueless people
+**will** mess up social convention soon or later.
 
 
 Loose the DAG robustness
 ````````````````````````````
 
-The other approach is
+The other approach use in Mercurial is to keep the mutable part of the history
+outside the DVCS constraint. This is the MQ approach of sticking a quilt queue
+over Mercurial.
 
-mq -- quilt
+This allow much more flexible workflow but two major feature are lost in the
+process:
 
-Conflict too much conflict
+:Graceful merge: MQ use plain-patch to store changeset content and patch have
+                 trouble to apply in changing context. Applying your queue
+                 becomes very painful when context changes.
 
-Linear
+:easy branching: A quilt queue is by definition a linear queue. Increasing risk
+                 of conflict
 
+It is possible to collaborate over versioned mq! But you are going ahead a lot
+of troubles.
 
-Deny a lot of option
-````````````````````````````
-
-
-
-[] rewrite
-
-[] exchange
-
-[] collaborate
-
+.. Ignore conflicts
+.. ```````````````````````````````````
+.. 
+.. Another ignored issue is conflicting rewritting of the same changeset. If a
+.. changeset is rewritten two times we have two newer version, duplicated history
+.. complicate to merge.
+.. 
+.. Mercurial work around by
+.. 
+.. The "One set of mutable changset == One developper" mantra is also a way to work
+.. around conflicting rewritting of changeset. If two different people are able to
+.. 
+.. The git branch model allow to overwrite changeset version by another one. But it
+.. does not care about divergent version. It is the equilent of "common ftp" source
+.. management for changeset.
 
 Facing The Danger Once And For All
 ------------------------------------------------
-The more effort you put to avoid instability, the more option you deny. And even
-most restrictive work flow can't garantee that instability will never show up!
+
+Above we saw that, the more effort you put to avoid instability, the more option
+you deny. And even most restrictive work flow can't guarantee that instability
+will never show up!
+
+Obsolete marker can handle the job
+```````````````````````````````````
 
 It is time to provide a full featured solution to deal with instability and to
 stop working around the issue! This is why I developing a new feature for
-mercurial called "Obsolete marker".
+mercurial called "Obsolete markers". Obsolete markers have two key properties:
 
 
-* Any changeset is we want to get ride of is **explicitly** marked as "obsolete"
-  by history rewritting operation..
+* Any "old" changeset we want to get ride of is **explicitly** marked as "obsolete"
+  by history rewriting operation.
 
-* Relations between old and new version of changesets are tracked by Obsolete
+  By explicitly marking the obsolete part of the history, we will be able to
+  easily detect instability situation.
+
+* Relations between old and new version of changesets are tracked by obsolete
   markers.
 
-By explicitly marking the obsolete part of the history, we will be able to
-easily detect appearance of unstability. By Storing a meta-history of changeset
-evolution we are able to easily resolve instability and edition conflict.
+  By Storing a meta-history of changeset evolution we are able to easily resolve
+  instability and edition conflict [#]_ .
 
+.. [#] edition conflict is another major obstable to collaboration. See the
+       section dedicated to obsolete marker for details.
 
+Improves robustness == improves simplicity
+````````````````````````````````````````````````
 
+This proposal should **first** be seen as a safety measure.
 
-No instability is still a bad situation.
-No instability is still a bad situation that should be avoided.
+It allow to detect instability as soon as possible
+
+::
+    $ hg pull
+    added 3 changeset
+    +2 unstable changeset
+    (do you want "hg stabilize" ?)
+    working directory parent is obsolete!
+    $ hg push
+    outgoing unstable changesets
+    (use "hg stabilize" or force the push)
+
+And should not not encourage people to create unstability
+
+::
+    $ hg up 42
+    $ hg commit --amend
+    changeset have descendant.
+    $ hg commit --amend -f
+    +5 unstable changeset
+
+    $ hg rebase -D --rev 40::44
+    rebasing already obsolete changeset 42:AAA will conflict with newer version 48:BBB
+
+While allowing powerful feature
+````````````````````````````````````````````````
+
+
+* Help to automatically solve instability.
+
+* "kill" changeset remotely.
+
+* track resulting changeset when submitting patch//pull request.
+
+* Focus on what you do:
+
+  I do not like the "all at once" model of history rewriting. I'm comfortable
+  with unstability and obsolete marker offer all the tool to safely create and
+  handle unstability locally.
+
+
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-'''A set of command to make changeset evolve.'''
+'''a set of commands to handle changeset mutation'''
 
 from mercurial import cmdutil
 from mercurial import scmutil
     ],
     '')
 def stabilize(ui, repo, **opts):
-    """move changeset out of they unstable state
+    """move changeset out of the unstable state
 
     By default only works on changeset that will be rebase on ancestors of the
     current working directory parent (included)"""
 
 @command('^gdown',
     [],
-    'update to working directory parent and display summary lines')
+    '')
 def cmdgdown(ui, repo):
+    """update to working directory parent and display summary lines"""
     wkctx = repo[None]
     wparents = wkctx.parents()
     if len(wparents) != 1:
 
 @command('^gup',
     [],
-    'update to working directory children and display summary lines')
+    '')
 def cmdup(ui, repo):
+    """update to working directory children and display summary lines"""
     wkctx = repo[None]
     wparents = wkctx.parents()
     if len(wparents) != 1:

hgext/obsolete.py

 changeset history. Standard changeset history versions files. The *obsolete*
 relation versions changesets.
 
-:obsolete:     a changeset that have been replace by another one.
-:unstable:     a non-obsolet changeset based on another one.
+:obsolete:     a changeset that has been replaced by another one.
+:unstable:     a changeset that is not obsolete but has an obsolete ancestor.
 :suspended:    an obsolete changeset with unstable descendant.
-:extinct:      an obsolete changeset without unstable descendant
+:extinct:      an obsolete changeset without unstable descendant.
                (subject to garbage collection)
 
 Another name for unstable could be out of sync.
 
 
-
 Usage and Feature
 =================
 
-
 Display and Exchange
-....................
+--------------------
 
 obsolete changesets are hidden. (except if they have non obsolete changeset)
 
-obsolete changesets are currently not exchange. This will probably change later
-but it was the simpler solution for now.
+obsolete changesets are not exchanged. This will probably change later but it
+was the simpler solution for now.
 
 New commands
-............
+------------
 
-a ``debugobsolete`` command has been added.
-
-It add an obsolete relation between too relation.
+A ``debugobsolete`` command was added. It adds an obsolete relation between two
+nodes.
 
 Context object
-..............
+--------------
 
-Context gain a ``obsolete`` method that return True if a changeset is obsolete
-False otherwise.
+Context gains a ``obsolete`` method that will return True if a changeset is
+obsolete False otherwise.
 
 revset
-......
+------
 
 Add an ``obsolete()`` entry.
 
 repo extension
-..............
+--------------
 
 To Do
------
+~~~~~
 
-* refuse to obsolete published changesets
+- refuse to obsolete published changesets
 
-* handle split
+- handle split
 
-* handle conflict
+- handle conflict
 
-* handle unstable // out of sync
+- handle unstable // out of sync
 
 """
+
 import os
 try:
     from cStringIO import StringIO
                     journalpath = self.sjoin(journalname)
                     util.copyfile(filepath, journalpath)
 
-        else: # XXX remove this bloc while breaking support to Hg 2.1
+        else: # XXX removing this bloc will break Hg 2.1 support
             def _writejournal(self, desc):
                 """wrapped version of _writejournal that save obsolete data"""
                 entries = list(o_writejournal(desc))
 
         @storecache('00changelog.i')
         def changelog(self):
-            # << copy pasted from mercurila source
+            # << copy pasted from mercurial source
             c = changelog.changelog(self.sopener)
             if 'HG_PENDING' in os.environ:
                 p = os.environ['HG_PENDING']
                 phases.retractboundary(repo, 2, expobs)
             finally:
                 lock.release()
-
-
+"""synchronize patches queues and evolving changesets"""
 
 import re
 from cStringIO import StringIO