
Why I Switched to Git From Mercurial - pilif
http://blog.extracheese.org/2010/05/why-i-switched-to-git-from-mercurial.html
======
mbrubeck
I've used Git for three years, at two different companies and various personal
and community projects. I sync my home directory between hosts using git, I
have administered multi-user git repos using gitosis, and I have been a GitHub
user since early 2008.

I started using Mercurial two months ago when I joined the Mozilla
corporation, and now use it every day on one of the biggest and best-supported
installations in the world. I also started using BitBucket for some of my
Mozilla-related personal projects.

It might be that I don't fully "get" Mercurial yet, but I still find myself
frequently missing Git. My first impression is that Git has a simple flexible
model that supports a complex front-end, while Mercurial has a simple
extensible front-end that ends up creating a somewhat more complicated model.

Any time I need to step outside the standard commit-merge-push workflow, I
find the higher level of abstraction between Mercurial's user commands and its
database makes it harder to understand what I'm doing, and sometimes prevents
me from doing what I want. Things like rewriting history (e.g. for rebasing),
or combining changes from multiple remote repos with different sets of
branches, are still possible in Mercurial - but they usually require plugins
to do well, there are more different incompatible ways to do them, and there
are more opportunities to mess up your repo.

More concretely, I find that MQ is the best way to do many tasks in Mercurial
that I would do in git with plain old branches and commits, and for many of
these uses MQ is both more complicated and less flexible than the equivalent
git commands. (But there are other uses where MQ is really better than the
alternatives.) I also find that it's much more annoying to manage short-lived
throwaway or topic branches in Mercurial, so much that I simply avoid using
them much of the time.

But perhaps I'm just brainwashed (or brain-damaged) from too many years with
Git. :)

~~~
jwr
Good point about MQ, before people pointed me to it, I was continuously
surprised by many things I could not easily do in hg.

The DVCS crowd looks down on centralized VCSses and points out that whenever
the answer to a VCS question begins with "well, you should have done X before
you did this…", it marks a failure.

Fair enough.

But I would extend that further — when I ask "how do I do X with this VCS", I
don't want to be told "well see, you don't really want to be doing X". Yes I
do want to, and I want a VCS that let's me do pretty much anything I want.
That's git's approach.

------
ErrantX
I use Mercurial and much much prefer it to Git (personal preference, I'll try
not to evangalize)

In part he is dead on.

hg really can't handle large repositories; but to be honest if you're working
with GB's of data then you're using the wrong tool :) period.

Point two is a "complaint" I agree with. The repository structure isn't
particularly good - it "works" for the most part but sometimes you just want
to kick it. And forget hacking around with it..

Silly things like "hg copy [file]" doesn't copy file history but does a
remove/add & cp/rm are another ball ache.

Ultimately hg is a _good_ tool; for lightweight, hackerish version control it
is great. Beyond that? Yeh, use Git.

~~~
tjogin
But isn't also Git just as good at the stuff you think hg is good at?

~~~
ErrantX
Yes.... though it is more complex (and in my experience a lot of that
complexity is not needed by most). So hg is a nice portable alternative.

~~~
charlesmarshall
What part do you find complicated about git? The basic commands are: git
clone, git add, git commit, git push ... most of these are handled by guis
(tortoise, gitx, etc) so all you have to do then is click the right button

~~~
ErrantX
Well, exactly. For the vast majority of people those are the only four
commands needed. So hg is a great alternative to git.

If you need something more complex or specialist then git is the clear winner.

~~~
weaksauce
I think the parent is trying to say that why use a tool that is "hackerish" if
they both do the same thing with the same few commands. Then if you need to do
something more complex you already have git.

Edit: iPad mistype.

~~~
ErrantX
I know this is glib but; it's more "raw" :)

But that's a personal preference. Git is just as good a choice.

------
pilif
personally, I really don't get the complaints about git's UI. OK. I understand
the confusion about what checkout does, though on the other hand, once you
know that, it won't happen to you.

But a revision control system failing to not corrupt or crash depending on the
data you put into it is, frankly, no revision control system.

Just like a database failing to return the same data back that you told it to
store and without telling you a problem occurred at store time is no database
either ( _cough_ mysql _cough_ ).

~~~
danh
"I really don't get the complaints about git's UI"

I think it's because git's data model is so minimal and elegant, and the UI is
anything but.

For me, it's not so much that the UI is quite bad (which it is), but that it
could have been brilliant.

~~~
etherealG
Perhaps you could elaborate on a UI design that would be brilliant. Even
better, code it, if you can improve do. I'll tell you what, if you even
succeed in describing such an interface, I'll build it for you.

~~~
danh
Oh, I didn't say that it would have been brilliant if I had built it. But I'll
bite anyway. Or at least provide a couple of thoughts.

The index is one of the key components in git, but it doesn't really have a
name or label in the UI. Say that it was called "index"; then the current "git
diff" would be equivalent to "git diff index", and the current "git diff
--cached" to "git diff index..HEAD". Less special cases to remember. IMHO, of
course.

The same way "git checkout index foo.c" would fetch foo.c from the index (I
don't even remember the magic incantation for doing that now). Etc.

Also, I still think that using the index should be optional: "git diff" should
default to "git diff HEAD", "git commit" should default to the current "git
commit -a", etc.

"git checkout" tries to do too much. It creates and switches to branches, and
copies blobs from the repository to the working tree. The first form is
reasonably safe, and bails out without --force if you do something stupid, the
second does not. At least for me, the only way to learn the difference is the
hard way.

The branch-switching should probably be done by "git branch" instead, and the
fetching of blobs by "git reset" (which sometimes already does this, but with
very confusing options; I never remember the difference between --soft,
--mixed, --hard, --mixed and whatever).

That's only a couple of changes that could have been made a long time ago. Now
it is definitely too late. Even if the git UI could be made smaller and more
logical (with a huge amount of work), it's not worth pissing off pretty much
every git user out there...

~~~
wfarr
I disagree on making `git commit -a` the default behavior for commits in git.
It discourages making nice, atomic commits.

~~~
danh
I agree that two-stage commits is a great feature to have. But there are
downsides to making it the default.

Obviously, it trips beginners up.

And it encourages committing stuff that may never have coexisted in the
working tree - and thus have never been tested together.

~~~
wfarr
I can't think of any reason for someone to commit changes that hadn't been
tested in the working tree or at least ran through the test suite before doing
so.

------
sreque
The author states three reasons for switching.

1\. Problems with storing big files in Mercurial. You can use the bigfiles
extension if you really want to manage large files with Mercurial.

2\. Inefficient renames. Making renames efficient is a currently recommended
GSoC project. I'm sure this will be fixed eventually even if no one picks it
up this summer.

3\. Destructive commands actually, well, destroying stuff. This point makes me
feel like the author knew git first, tried mercurial out, and switched back,
making the blog post a little misleading. I don't know how you could expect a
delete not to be a delete unless you were familiar with something like git
already. If I were to run a delete command in Mercurial, I would read the
documentation on the command first to make sure it created a backup for me.
Only if it then failed to create this backup would I complain. Also, I think I
prefer the bundle approach of Mercurial. You can always rename the bundles to
keep track of them. You could even write your own extension in 5 lines that
ran a destructive command and immediately unbundled the created bundle to
restore your changesets, exactly duplicating git's functionality.

The first two issues he mentions I would consider to be actually valid
complaints against Mercurial, the third just a personal preference of the
author. I would consider neither of them to be major game-changing issues.

~~~
vtail
> I don't know how you could expect a delete not to be a delete unless you
> were familiar with something like git already.

Ability to control and be able to reverse _any_ changes you make to the source
code tree is an essential feature of version control system - precisely
because you don't know in advance what will work and what won't. The fact that
people are not used to that simple idea just shows how broken are most of the
other tools out there.

There is no reason not to want an unlimited undo for almost everything,
especially today when disk space is so cheap.

~~~
DrJokepu
Maybe this is not that much relevant for DVCSs but in 'classic' VCSs such as
SVN an 'obliterate' command would be quite useful, think about the case when
someone accidentally commits something highly sensitive (such as private keys)
to version control. People make mistakes all the time, either way.

~~~
charlesmarshall
you can use commands like git filter-branch & git rebase to change your
history - [http://www-cs-
students.stanford.edu/~blynn/gitmagic/ch05.htm...](http://www-cs-
students.stanford.edu/~blynn/gitmagic/ch05.html)

~~~
Xurinos
"git rebase" on its own does not permanently alter history. It creates a new
branch that looks like a new history, but you can get back to the original
history.

"git gc" will prune the unused old histories for that permanent effect.

~~~
Vitaly
even "git gc" will not do it for a while. the old history will still be
referenced from the reflog for some time (I think default is 30 days)

------
avar
This is always relevant: <http://keithp.com/blogs/Repository_Formats_Matter/>

"I would like to argue that none of the user-interface and high-level
functional details are nearly as important as the fundamental repository
structure. When evaluating source code management systems, I primarily
researched the repository structures and essentially ignored the user
interface details. We can fix the user interface over time and even add
features. We cannot, however, fix a broken repository structure without all of
the pain inherent in changing systems."

Keith makes a good point. While Git's interface is lacking in some areas,
those things can be fixed in the higher level porcelain. Picking a system with
a nicer interface whose plumbing is uglier will lead to problems further down
the road.

------
durin42
With respect to his claim hg lost data for him, he was using mq without really
understanding it or using a versioned queue. mq is disabled for a reason, and
he enabled it without fully understanding the risks and ways of mitigating
those risks. I've discussed this with him at times, but the message never
seems to connect.

~~~
garybernhardt
Augie, I understand what you're saying, and I don't buy it. Git, when taken as
a full DVCS capable of rewriting history, is safer than Mercurial, when taken
as a full DVCS capable of rewriting history.

A DVCS that is incapable of rewriting history is, for me, a nonstarter, so I'm
not interested in talking about "well, if you turn off the interesting parts
of Mercurial, it's perfectly safe!"

You can either use Mercurial in a mode where it's not at all equivalent to
Git, but safe (extensions off), or you can use it in a mode where it's
somewhat equivalent to Git, but might lose your data.

With Git, I can mutate history without the slightest bit of fear, often just
to see what will happen. Does this giant branch I discarded two months ago
rebase cleanly over master? Try it. If the rebase completes but I don't like
it, I "git reset mybranch@{1}" and everything is good. And that safety net is
always there.

In Mercurial, I have to stop and think every time. Even if the command does
dump a bundle, restoring from it is a special case, and I'm going to have to
go dig up the bundle file, and in some cases it might not be there and I'll be
screwed. In Git, there are no special cases, I always know exactly how to
recover, and the recovery mechanism is always there.

Once more, to be clear: In Git, it is always there. Always there!

~~~
utx00
i guess i will have to try git to be sure, but i really don't see a difference
here. usually if i'm going to try something drastic, i try it on a clone that
i know i can throw away.

~~~
garybernhardt
I often do it multiple times per minute. That wouldn't fly if each required a
clone. :) (See another post I made in this thread for what I'm doing that
involves so much history mutation.)

------
pacemkr
"It's just an interface, though, and this is a tool you are going to use every
day..."

This summarized, for me, why I use hg. It is a tool I am going to use everyday
and it's not ok for this tool to have a crappy interface. My hard drive space,
that I don't care about.

~~~
j_baker
git's interface isn't terribly intuitive, but it isn't _that_ bad. Once you
get the hang of it, it makes sense.

~~~
anthonyb
I really don't follow this argument. git's interface is a giant turd. I've
been using it for months, and it still hasn't stuck, no matter what tutorials
I read. The normal workflow needs far too many commands and special options,
local vs. remote branching seems to do weird things, and the error messages
are completely obtuse.

------
psranga
I thought Git handled huge files poorly too. What I'd read was that most algos
in git assume that the whole file in revision control can be held in memory at
once to do things like diff.

Has this changed, or was I always mistaken, or this guy talking about the sum
of file sizes being a few gig?

~~~
avar
It still handles them poorly by default. You can do things like edit
.gitattributes to say that e.g. a *.binary file should be treated specially,
but Git's still not a good system for e.g. archiving HD video.

Some of this can be fixed, but a lot of it is probably not going to change.
When you git-add something it has to checksum the old data + new data. That's
going to be a pretty expensive operation when you have 50TB of data.

There's no DVCS that I'm aware of that handles large binary files as well as
say Perforce or Subversion.

Check out this project for more info on tuning Git for big files:
<http://caca.zoy.org/wiki/git-bigfiles>

------
jozeph78
Thanks for this good article. I took a 15 minute tour of both HG and Git and
felt that hg was overall a better experience, but felt if the community is
moving towards Git there has to be some good reason. I'm always a fan of the
underdog, so I've been asking everyone why Git (besides Github of course).

This is the first article that gives real pitfalls of one vs the other. I
enjoyed the read and would love to hear more as well as counter arguments.

~~~
charlesmarshall
although a bit biased, <http://whygitisbetterthanx.com/> gives you the
highlights of what git is good at.. for me its the simple branching coupled
with easy stashing

~~~
tzs
Being biased is OK, but that site is just flat out wrong on some of its
points. Mercurial has cheap local branching. There are good hosting services
for hosting Mercurial repositories.

