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