# HG changeset patch # User Pierre-Yves David # Date 1332353364 -3600 # Node ID 92b073d13f2d184d4e8015f50a80568d4aa4e5a7 # Parent 1a6ae8d8f1041ed4ea4b8de0669eb210a7c28180 more doc update diff -r 1a6ae8d8f104 -r 92b073d13f2d docs/evolve-intro.rst --- a/docs/evolve-intro.rst Wed Mar 21 12:11:43 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ ----------------------------------------- -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 diff -r 1a6ae8d8f104 -r 92b073d13f2d docs/index.rst --- a/docs/index.rst Wed Mar 21 12:11:43 2012 +0100 +++ b/docs/index.rst Wed Mar 21 19:09:24 2012 +0100 @@ -8,35 +8,44 @@ The effort is splitted in two part: - * The **obsolete marker** concept that - - - - add an alternative to strip to remove changeset from a repository. + * The **obsolete marker** concept aiming to provide and alternative to strip to + get ride of changesets. - * The changeset evolution UI + * A mercurial extension: **evolve** that rewrite using *obsolete marker* + under the hood. + - to replace mq. - - - adding in mercurial core an new concept of **obsolete marker** in mercurial - core, +regarding mercurial internals, the first and most important step is the +**obsolete marker**. However most user will never be directly exposed to the +concept. For this reason document about changeset evolution are put first. - * + +Evolve: A robust alternative to MQ +==================================== +* Using the obsolete marker concept, (see next section for advantage of the + obsolete marker) +* provide a more robust alternative for mq covering any 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 + implication of the **obsolete marker** concept. I do not recommend + non power user to test this at this stage. + + Production ready version should hide such details to normal user. + +To enable the evolve extension use:: + + $ hg clone http://hg-dev.octopoid.net/hgwebdir.cgi/mutable-history/ + $ mutable-history/enable.sh > ~/.hgrc -Evolve: A new UI to replace MQ -================================= - -For user .. toctree:: :maxdepth: 1 - evolve-intro tutorial evolve-faq from-mq diff -r 1a6ae8d8f104 -r 92b073d13f2d docs/obs-concept.rst --- a/docs/obs-concept.rst Wed Mar 21 12:11:43 2012 +0100 +++ b/docs/obs-concept.rst Wed Mar 21 19:09:24 2012 +0100 @@ -35,7 +35,7 @@ -.. figure:: ./figures/example-1-update.png +.. figure:: ./figures/example-1-update.* *Updating* a changeset @@ -43,20 +43,20 @@ -.. figure:: ./figures/example-2-split.png +.. figure:: ./figures/example-2-split.* *Splitting* a changeset in multiple one Create one obsolete marker ``([B1, B2] obsolete B)]`` -.. figure:: ./figures/example-3-merge.png +.. figure:: ./figures/example-3-merge.* *Merging* multiple changeset in a single one Create two obsolete markers ``([C] obsolete A), ([C] obsolete B)`` -.. figure:: ./figures/example-4-reorder.png +.. figure:: ./figures/example-4-reorder.* *Moving* changeset around @@ -65,7 +65,7 @@ -.. figure:: ./figures/example-5-delete.png +.. figure:: ./figures/example-5-delete.* *Removing* a changeset: @@ -122,7 +122,7 @@ 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 +.. figure:: ./figures/error-obsolete.* Rebasing `B` and `C` on `A` (as `B'`, `C'`) @@ -148,7 +148,7 @@ *Non-obsolete* changeset based on *obsolete* one are said **unstable** -.. figure:: ./figures/error-unstable.png +.. figure:: ./figures/error-unstable.* Amend `A` into `A'` leaving `B` behind. @@ -187,7 +187,7 @@ * *obsolete* changeset with *unstable* descendants, said **suspended**. -.. figure:: ./figures/error-extinct.png +.. figure:: ./figures/error-extinct.* Amend `A` and `C` leaving `B` behind. @@ -210,7 +210,7 @@ different versions. -.. figure:: ./figures/error-conflicting.png +.. figure:: ./figures/error-conflicting.* Conflicting rewriting of `A` into `A'` and `A''` diff -r 1a6ae8d8f104 -r 92b073d13f2d docs/tutorials/tutorial.t --- /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 diff -r 1a6ae8d8f104 -r 92b073d13f2d tests/test-tutorial.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-tutorial.t Wed Mar 21 19:09:24 2012 +0100 @@ -0,0 +1,1 @@ +../docs/tutorials/tutorial.t \ No newline at end of file diff -r 1a6ae8d8f104 -r 92b073d13f2d tests/tutorial.t --- a/tests/tutorial.t Wed Mar 21 12:11:43 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,677 +0,0 @@ -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