diff -r 5fa287e5087e -r d702f0d26c6a tests/test-tutorial.t --- a/tests/test-tutorial.t Tue Aug 07 15:38:20 2012 +0200 +++ b/tests/test-tutorial.t Tue Aug 07 16:02:50 2012 +0200 @@ -1,1 +1,775 @@ -../docs/tutorials/tutorial.t \ No newline at end of file + +Initial setup +------------- + +This Mercurial configuration example is used for testing. +.. Various setup + + $ cat >> $HGRCPATH << EOF + > [ui] + > logtemplate ="{node|short} ({phase}): {desc}\n" + > [diff] + > git = 1 + > [alias] + > # "-d '0 0'" means that the new commit will be at January 1st 1970. + > # This is used for stable hash during test + > amend = amend -d '0 0' + > [extensions] + > hgext.graphlog= + > EOF + + $ hg init local + $ cat >> local/.hg/hgrc << EOF + > [paths] + > remote = ../remote + > other = ../other + > [ui] + > user = Babar the King + > EOF + + $ hg init remote + $ cat >> remote/.hg/hgrc << EOF + > [paths] + > local = ../local + > [ui] + > 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 + $ 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 + +Its first version is shared 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" + +This history is very linear + + $ hg glog + @ d85de4546133 (draft): adding fruit + | + o 4d5dc8187023 (draft): adding condiment + | + o 7e82d3f3c2cb (public): Monthy Python Shopping list + + +But a typo was made in Babanas! + + $ 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 + +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 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! + + $ 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 + +A new changeset with the right diff replace the wrong one. + + $ 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 + # 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. + + $ cd ../remote + $ hg up -q + $ sed -i'' -e 's/Spam/Spam Spam Spam/' shopping + $ hg ci -m 'SPAM' + $ cd ../local + +I'll get this remote changeset when pulling + + $ 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 this remote head is immutable + + $ hg log -G + o 9ca060c80d74 (public): SPAM + | + | @ 0cacb48f4482 (draft): adding fruit + | | + | o 4d5dc8187023 (draft): adding condiment + |/ + o 7e82d3f3c2cb (public): 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 + + +My local work is now rebased on the remote one. + + $ hg log -G + @ 387187ad9bd9 (draft): adding fruit + | + o dfd3a2d7691e (draft): adding condiment + | + o 9ca060c80d74 (public): SPAM + | + o 7e82d3f3c2cb (public): 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 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 prune . # . 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 -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 changesets. + + + $ 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 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" + +You can use 'rebase -r' or 'graft -O' for that: + + $ hg up 'p1(8d39a843582d)' # going on "bathroom stuff" parent + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg graft -O c48f32fb1787 # moving "SPAM SPAM" to the working directory parent + grafting revision 10 + merging shopping + $ hg log -G + @ a2fccc2e7b08 (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 + + +We have a new SPAM SPAM version without the bathroom stuff + + $ grep Spam shopping # enouth spam + 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 a2fccc2e7b08bbce6af7255b989453f7089e4cf0 + # 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) + +To make sure I do not push unready changeset by mistake I set the "bathroom +stuff" changeset in the secret phase. + + $ hg phase --force --secret 8d39a843582d + +we can now push our change: + + $ hg push 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 get the bathroom change in line again + + $ 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 "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 the repo you interact +with is "not publishing". Otherwise you will get the previously observe +behavior where exchanged changeset are automatically published. + + $ cd ../remote + $ hg -R ../local/ showconfig phases + +the localrepo does not have any specific configuration for `phases.publish`. It +is ``true`` by default. + + $ hg pull local + pulling from $TESTTMP/local + 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 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 + + + + +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 pull) + $ 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 the local repo "non publishing" + + $ echo '[phases]' >> ../local/.hg/hgrc + $ echo 'publish=false' >> ../local/.hg/hgrc + $ echo '[phases]' >> .hg/hgrc + $ echo 'publish=false' >> .hg/hgrc + $ hg showconfig phases + phases.publish=false + $ hg -R ../local/ showconfig phases + phases.publish=false + + +I can now exchange mutable changeset between "remote" and "local" repository. + + $ hg pull local + pulling from $TESTTMP/local + 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 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 the mutable "bathroom" on. + + $ hg up 8a79ae8b029e -q + $ cat >> shopping << EOF + > Giraffe + > Rhino + > Lion + > Bear + > EOF + $ hg ci -m 'animals' + +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 -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! + + + $ 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) + 1 new unstables changesets + + +The new changeset "animal" is based one an old changeset of "bathroom". You can +see both version showing up in the log. + + $ hg log -G + o 9ac5d0e790a2 (draft): animals + | + | @ ffa278c50818 (draft): bathroom stuff + | | + x | 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 + + +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: push includes an unstable changeset: 9ac5d0e790a2! + (use 'hg stabilize' to get a stable history or --force to ignore warnings) + [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. + + $ 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. + + $ 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 remote + 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 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 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + +Relocating unstable change after prune +---------------------------------------------- + +The remote guy keep working + + $ sed -i'' -e 's/Spam/Spam Spam Spam Spam/g' shopping + $ hg commit -m "SPAM SPAM SPAM" + +I'm pulling its work locally. + + $ 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 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 prune the animal changeset: + + $ hg prune 437efbcaf700 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory now at ffa278c50818 + 1 new unstables changesets + + +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 -G + o ae45c0c3092a (draft): SPAM SPAM SPAM + | + x 437efbcaf700 (draft): animals + | + @ 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 + + + $ hg log -r 'unstable()' + ae45c0c3092a (draft): SPAM SPAM SPAM + +# XXX make prune stabilization works +# $ hg stabilize --any +# merging shopping + + $ hg graft -O ae45c0c3092a + grafting revision 17 + merging shopping + + $ 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.