[darcs-users] dvcs article

Stephen J. Turnbull stephen at xemacs.org
Wed Feb 4 02:44:49 UTC 2009

Trent W. Buck writes:
 > Matthias Andree <matthias.andree at gmx.de> writes:

 > > Conventionally, Mercurial seems a bit closer to DARCS's model in that it
 > > has apparently not encouraged local branches as strongly as Git has, but
 > > that's not a technical reason AFAICT, but just common use of lead
 > > developers/supporters.

For starters, Mercurial's implementation of "named branches" is just
broken.  Every commit belongs to a branch, and only one branch.  That
means that neither the fork node nor the merge node can belong to both
branches.  If you use update naively, then further work on the branch
B in

B    1
    / \       must follow as "hg update B; hg commit" yielding
A  0-2-3

B    1---4
    / \       or as "hg update B; hg merge" yielding
A  0-2-3

B    1---4
    / \ /     which are both pretty unintuitive to me, as commit 3 is
A  0-2-3

never on branch B, despite merging the branch into the mainline A.
Also, in the last graph, the default branch has no head as far as hg's
automatic DAG management is concerned!  In git, I would simply use
"git checkout B; git merge A" which would result in a fastforward of
B's head to commit 3.

Note that in the graphs above, rows are significant: only commits on
the same row are in the same branch.  So pulling from upstream will
probably cause another merge into your branch, which is almost
certainly not what you want.  OTOH, in XEmacs I already see a few
places where the commit DAG looks like this:

    / \ \
A  0-2-3-6-...

(note, not a named branch).  This works fine (no explosions), but I
suspect it's altogether too easy to forget to merge commit 4.

 > The technical reason might be that hg's "update" command, which is used
 > to change between in-branch heads, tends to be make my repo explode in a
 > fashion that I cannot work out how to recover from, and therefore I have
 > to make a completely fresh clone of upstream and re-record all my
 > patches by hand.

Heh heh heh "technical" heh heh "let's do that again, Beavis" heh heh.

The technical reason is that hg doesn't distinguish between the
(implicit) universal graph of tree states and the historical DAG of
commits.  This is no problem for the kind of developer who is always
charging forward, and whose primary tool for looking at history is
"bisect".  However, my experience is that if you think of VCS as a
trail of breadcrumbs you leave behind you as you traverse the maze of
trees, you pretty quickly find that hg frequently disagrees with you
about where you "should" be making any given commit, and it requires a
fair amount of effort to get hg to make the workspace conform to your
idea of where to commit.

 > This has happened several times for me with hg merely because of a merge
 > conflicts between my HEAD and upstream's HEAD; the result being that I
 > actually have to use hg more like svn than a dVCS -- frantically pushing
 > changes back upstream after every commit, in constant fear of a merge
 > conflict.

If you don't use named branches, I suspect everything will be OK (ie,
the repos won't explode).  You may find that you need to do a lot more
merging than you would expect, but the fetch extension will hide that
from you (unfortunately, it doesn't hide it from "hg log").

Now, in Darcs what happens is quite different.  A little reflection
will show that any hunk patch can be represented as a pair of trees,
but actually means an equivalence class of (before,after) tree pairs.
Whether a particular tree can be the "before" tree is computed lazily
(if not, you get a merge conflict).  It seems to me the psychology of
these equivalence classes is that there is a sort of continuity
property that "most" of the trees "close" to the tree you're currently
thinking about will trivially be before or after trees, so like hg you
get intuitive behavior when "charging ahead".  But because a patch is
an equivalence class, you are implicitly characterizing a much larger
set of "before" trees, and thus Darcs also has intuitive properties
"far" from your current tree state.  hg doesn't allow you to "jump" to
a far away state very easily, so lacks intuition (to me).

I suspect that "git people" implicitly have the tree-pair model of
revision control, and thus don't see "rebase" as a history rewrite or

More information about the darcs-users mailing list