Mutable History and collaboration
=====================================================================
History mutation
=====================
.. Albert Beugras
.. René de Robert
Here is small introduction of
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'' 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 # XXX --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'' '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
> Toothbrush
> Towel
> ... More bathroom stuff to come
> EOF
$ hg ci -m 'bathroom stuff' -q # XXX remove the -q
$ sed -i'' 's/Spam/Spam Spam Spam/g' shopping
$ hg ci -m 'SPAM SPAM'
$ hg ttlog
d19fa1996cc7: 'SPAM SPAM' (ready)
e64eb196cfd1: '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(e64eb196cfd1)' --traceback
merging shopping
$ hg tglog -r '::(. + e64eb196cfd1)'
@ e96fa9b78e3d: 'SPAM SPAM'
|
| o e64eb196cfd1: '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 e96fa9b78e3d2e21b604d4e05582bb1906a9bc59
# 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
collaboration
====================
We create a central repo (because most workflow include this central repo
$ cd ..
$ hg init central