Source

mutable-history / doc / simple-tuto.t

The default branch has multiple heads

Full commit
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