Mercurial vs git

Theodore Tso tytso at mit.edu
Fri Jan 5 13:22:51 CST 2007


> Viz complexity, the cogito suite (that wraps around git) completely
> hides the index, hides a lot of other things, and provides as simple an
> interface as hg. Also, with git, just do   git commit -a (assuming
> .gitignore is correctly set up) and forget the index exists. There is a
> lot of power to having the index, but you aren't forced to deal with it
> if you don't care. Sacrificing needed functionality to gain simplicity
> is a bad tradeoff, and that is the essence of the git / hg differences
> for me.

I would *not* recommend the use of cogito; it does things sufficiently
differently from git that in the long run, your users will be running
into traps.  Git 1.5.0 (in prelease) has been simplifying things so
that cogito is less necessary, and folks who get trapped into cogito
will in the long run be more confused.

You still need to remember the index.  If you create a file foo.c, do
a "git add foo.c", and then modify foo.c, "git commit -a" will *not*
do what you expect.  It will commit the version of foo.c at the time
that you executed the the "git add foo.c" command.  If you
subsequently modify foo.c, you have to remember to re-execute the "git
add foo.c" command, or use the "git update-index" command.

> >git branch -d : clone -r
> 
> hg clone -r is much less capable, requires a lot of fiddling, etc. to do
> the equivalent of git -D tmp/stupidbranch while keeping the 50 other
> branches and all history.

The real question here is how do you do your development.  With
mercurial, typically experimental work which is yet to be merged into
the mainline repository is simply kept in a separate directory with a
separate repository.  

Other people will use patch queues, either by using quilt or mercurial
queues (mq) to maintain work that hasn't been merged into the
production tree.   

Some folks prefer to store patches in a "git topic" branch and then
constantly use git rebase to rewrite history.  I find this is actually
more confusing, but it's really a matter of what individual developers
feel comfortable with.  The problem with a big project with a lot of
developers is the choice of a particular SCM can sometimes force
certain workflows onto all of the developers.

So before trying to choose between git and hg, you might want to take
a step back and consider the workflow that *ALL* of the developers
will be comfortable with.  Clearly your git champion is comfortable
with git-optimized workflows, and as long as he gets to control the
criteria, he will get to control the outcome.

It's like choosing a car --- is the criteria, "will contribute least
to global warming", or "can cross 3 feet of standing water"?  One
choice will dictate the Prius; the other an H1 Hummer....

> I am not reverting a single checkin, not necessarily even a simple
> sequence. Could be commits 1 4 8 12 on a branch with 23 other things.
> Also, git rebase is essential in the process. Keep in mind, we do not
> actually do linear development, things do not happen in a particular
> order and we need the tool to let us merge things in the order we need,
> not the order convenient to the tool.

This is a developer workflow question again.  "git rebase" is one way
to do things, but it's certainly not the only way.  If you use "git
rebase" and you have to deal with a merge conflict, git does ***NOT***
have any good tools for dealing with it.  You end up using very manual
commands to resolve the conflicts.  

In general, Hg has much better intergration with graphical merge tools
than git does.  (Probably because Linus doesn't have much use for
graphical merge tools.  :-)


At the end of the day, what I told folks at the end of my "Bzr, git,
and hg, oh, my!" class, was that all of the tools were better than
rcs/cvs/svn, but which one you choose is largely one of individual
preference and project development workflow.  For e2fsprogs I chose
hg, because at the time, git hadn't yet developed packed objects, so
in fact hg was about ten times more space efficient than git.  

More importantly, though, was that for an OSS project to succeed, you
don't want your SCM to be an impediment for people to get involved,
and git was in my opinion, at that time, far too scary for mere
mortals to use.  Git *has* been getting better, but I suggest you read
the git man page in full, and then read the "git diff" man page in
full, and then all of the man pages that you need just to figure out
what options you can give to "git diff", so you know what you are
getting yourself into.  

Then try to resolve a merge with conflicts in hg (with a graphical
merge program installed), and try to do the same thing with git.

That being said, my opinion (speaking as someone who uses both
mercurial for e2fsprogs and git for Linux kernel development), is that
git does have a whole bunch of neat tricks that hg can't do, and there
are certain things that git just screams in terms of speed--- once you
figure out the tricks of how to make things work.  (That's the bits of
git that makes the poor developer trying to *learn* how to use git
_to_ scream, in frustration.)

The way I did it involved reading the git mailing list for about 3
months (I was signed up to teach the a distributed SCM class, so it
forced me to get much more familiar with git), and played with it for
probably a total of full week, full time, in order to get really
familiar with git.  And this is was for someone who was already
familiar with BitKeeper and Hg, so I already grokked the basics of
distributed SCM's.  But the git documentation is so horrific that if
you want to be an advanced user, it takes a lot of work.  (Someone who
only needs to check in changes and use a few magic recipies, and
doesn't need to care about the options to "git diff" probably could
get up to speed much faster, granted, but sooner or later they will
run into git's quaint documentation, which is in many case, just a few
steps above reading the source code, which could trigger them to go
running away screaming into the distance.)

						- Ted

P.S.  The magic sequence to repack a git repository to minimize its
space is:

git pack-refs --prune
git reflog expire --all
git repack -a -d -f -l
git prune
git rerere gc

Believe it or not, git users were normally expected to type these
commands by hand as necessary, and it was just in the past few weeks
(not yet released, but it will be in git 1.5.0) where all of the above
was packaged into the command "git gc".   :-)



More information about the Mercurial mailing list