Subject: Re: [VOTE] git versus mercurial (for DragonflyBSD)

From: Jakub Narebski <[email-masked]>
Date: Mon, 27 Oct 2008 11:57:18 +0100

Dnia poniedziałek 27. października 2008 10:29, Benoit Boissinot napisał:
> On Mon, Oct 27, 2008 at 2:52 AM, Jakub Narebski <[email-masked]> wrote:
>> On Mon, 27 Oct 2008, Arne Babenhauserheide wrote:
>>> Am Sonntag 26 Oktober 2008 19:55:09 schrieb Jakub Narebski:
>>>>
>>>> I agree, and I think it is at least partially because of Git having
>>>> cleaner design, even if you have to understand more terms at first.
>>>
>>> What do you mean by "cleaner design"?
>>
>> Clean _underlying_ design. Git has very nice underlying model of graph
>> (DAG) of commits (revisions), and branches and tags as pointers to this
>> graph.
> 
> Git and Mercurial are very close from that point of view.
>
> Mercurial explicitely disallow octopus merges (and we don't think there's
> a good reason to allow them, although I agree with Linus, they look very nice
> in gitk ;) ).

From what I see Mercurial disallows octopus merges (merges with more
than two parents) because of its rigid-record database repository
design, while Git is more like object database.  Fixed width records
of VMS vs delimited records of Unix... There is simply place on
zero, one or two parents (two parent fields, which can be null) in
Mercurial changerev format.

By the way flexibility of Git design allowed to add 'encoding' header
to commit message (if commits message is encoded not in utf-8) after
the fact, without affecting older repository data, and playing well
with old git installations which do not understand this header.

> And we don't have "branches as pointer" in core, but the bookmark
> extension does that.

I disagree. Mercurial implementation of tags is strange, and from
what I remember and from discussion on #revctrl implementation
of local named branches is also strange (CVS-like). They are IMHO
not well designed.

Also the 'hidden' branches after fetching from remote repository
(hg pull) but before merging (hg update) are IMHO worse design
than explicit remote-tracking branches in Git, especially in presence
of multiple [named] branches in repositories.

> Apart from that I think the underlying format are interchangeable,
> someone could use the git format with the hg ui, or use revlogs
> (the basic format of mercurial) like packs.

I don't think so. The 'content addressed filesystem' idea of Git
is quite pervasive along Git implementation and Git thoughtflows.

> 
> The only special thing about revlogs is the linkrev stuff, it's a
> pointer to the first revision that introduced an object, so we can
> easily find what to send in our network protocol (we don't have to
> read the manifest, ie the "tree" of objects"). linkrev can be useful
> to speedup "hg log" too.

At first I thought: what a nice idea... but then I realized that in
distributed environment there is no way to define "first revision that
introduced an object". Take for example the following history 
(independent introduction):

  .---.---.---.---x---.---.---.
           \
            --x---.---.

where both 'x' have the same version of an object. The top branch
appeared first in current repository, but the bottom branch had 'x'
with earlier timestamp (earlier authordate).

Git just relies on the fact that traversing revision is a part of it
that is heavily optimized and really fast. Git very much by design
doesn't store any backlinks in repository object database.

>> I have read description of Mercurial's repository format, and it is not
>> very clear in my opinion. File changesets, bound using manifest, bound
>> using changerev / changelog.
>>
> 
> just do a s/// with the git terminology:
> filelog -> blob
> manifest -> tree
> changelog -> commit object

True. But as I see it they are bound in reverse order in Mercurial:
deltas are stored in filelog, filelogs are bound together in manifest,
manifest are bound using changelog, while in Git commit object
references tree (and parents), trees references blobs, and blob store
content of a file. But that might be just my impression.

.......................................................................

By the way, going back to the matter of choosing version control system
for DragonflyBSD; some time ago I have written post
 * "Mercurial's only true "plugin" extension: inotify... 
    and can it be done in Git?"
   http://thread.gmane.org/gmane.comp.version-control.git/76661
   (current answer: it is possible using 'assume unchanged' bit)
about how nearly every Mercurial extension has equivalent functionality
in Git. 

But what about the reverse, about the following features and
issues in Mercurial:

 * Merging in presence of criss-cross merges[1], and in presence of
   file renames, i.e what merge-recursive does in Git.

 * git-rerere, reusing recorded resolution of conflicted merges.
   Resolving the same merge happens often if you use topic branches
   and trial merging.

 * git-grep that allows you to "and" the match criteria together,
   and also pick a file (not a line) that matches all the criteria;
   and of course allow searching given revision and not only working
   directory.

 * pickaxe search (git log -S) which contrary to blame/annotate
   allow to find commit which _deleted_ given fragment.

 * easy management of multiple repositories you fetch from with 
   remote-tracking branches and git-remote command.

 * blame that follows block-of-line movement (it was invented by Linus
   as a vision long time ago, but it took very long time to materialize).

 * a way to review merge resolution, something that is done in git
   by using combined diff format

 * git-stash, allowing to stash away changes to go back to them later;
   it allows to stash away even partially resolved merge conflict
   (merge resolution in progress).

 * git-filter-branch (based on cg-admin-rewrite-hist), which allow
   to rewrite history for example to remove file which should never
   be added to version control (for example because of copyright
   or license).

References:
===========
[1] http://revctrl.org/CrissCrossMerge
    BTW I wonder why reverting spam is made so hard on revctrl.org wiki
  
-- 
Jakub Narebski
Poland