--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/tutorials/tutorial.t Wed Mar 21 19:09:24 2012 +0100
@@ -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