Git doesn't really have changesets as first order objects; it has snapshots. Each commit is the hash of a snapshot of the tree at that point, together with the commit message and the hash of any (at least one) parent commits. This is pretty much the entire data model. The rest just pops out, which is why it is so elegant.
Minor correction: there does not have to be at least one parent commit. A commit can have no parent. The root commit, for example, should be parentless.
A repository can have more than root. For instance, I have a repository that was formed from merging two separate repositories. From a code history point of view, the two repositories are unrelated, so in the merged repository each has its own root.
Github also takes advantage of this; if you make an empty branch called "gh-pages", and put static html (and css, js) in it, Github will host them for you.
I've also used it to greenfield some ideas in the same project. Its a bit of a hack to create one, though:
git symbolic-ref HEAD refs/heads/newbranch
rm .git/index
git clean -fdx
<do work>
git add your files
git commit -m 'Initial commit'
Gah, I kinda came to this hoping to stick up for hg yet again. But a lot of these gripes are accurate.
It's not likely to change though. And here's the dice:
If you want something that "just works" and is awesome from the command line Mercurial is your best friend. If you may be facing borderline case that will wrap you in tape, Git is a better option.
And let's be honest, if you don't think you'll ever face such a borderline case you're being naïve or shortsighted. Just take the time to learn git. Like learning to use unix or $EDITOR you will not regret it.
With whatever git-hg bridges are available you can probably still use hg if you really like it. Could be wrong on that but iirc they exist.
An interesting article, if a little incoherent. It seemed to bounce around a bit much.
There are some reasonable means of local git sharing, by the by: the old gitjour project was fun and more recently there's gitosis and gitolite. You could also leverage Dropbox or similar, or actually work with individual repositories.
Bananajour and the Git server also work just as well. Any git repository can also act as a remote, and if it is made accessible over network, then you have essentially duplicated a git server.
In all fairness, hg serve is much easier to use than git daemon. It works on windows, for once, and you don't have to be aware of all kind of border cases w.r.t. aliases, etc... Still recently, I got issues accessing a git repo in which I did "git daemon --export-all" - I ended up making it work by executing git daemon outside the repo, which is a bit weird.
Am I the only one who thinks picking a DVCS tool based on the GUI is a bad idea? It seems to me that hg and git were designed to be used from a command line, and (for git at least) it works brilliantly. The GUI DVCS frontends try to hide a lot of the complexity of various tasks from you, but in that insulation you also end up with a clouded view of how things actually work, leading to the branching/merging mistakes the author talks about.
He didn't write GUI, he wrote "git UI". (Or at least that's what it says now. He may have edited after posting.) So he's not picking his DVCS based on graphical user interfaces.
And I think any tool's user interface is fair game for criticism. (Though other than the infamous "How do you delete a remote branch?" issue, I like git's user interface just fine.)
"GUI" is never explicitly mentioned, but after re-reading, I'm still not sure he _didn't_ mean a GUI, but neither am I sure that he certainly meant the CLI. I've never had a problem with the git CLI, I actually preferred it over the hg one (git pipes the log into 'less' for example, and lists entries in a sane reverse order so that the most recent log entry is on top). Maybe I'm just sensitive?
Hmm, using hg for Windows last summer, it never failed to do exactly the opposite of what I described. Perhaps its just a Windows thing, or the version of Mercurial I was using.
Yes, because Windows doesn't have less. It does whatever makes sense on each platform -- so on Windows it'll also use notepad for commit messages by default, and look for both .hgrc and Mercurial.ini in the home directory.
The pager and editor are configurable, of course. I have it set up to use emacsclient on Windows.
...and I would never hire anyone who perpetuates that myth. I converted a large (50+) group of developers to git from an old, horrible system which will go unnamed. Only the stupid ones complained about the switch. Sorry, it's true.
Ya, I'm a little bruised over the flames that ensued during the transition but I think we're better off after having bitten the bullet. The biggest problem was always close-minded people, it was never the technology.
The git model is good enough that we use it in spite of the bad CLI, not because of it. Just off the top of my head:
* the HEAD^2~3 syntax is so obscure that I can't believe anyone actually uses it; I always give up and get a commit name from the log instead
* it will cheerfully give you a branch named refs/heads/R/B having no relationship with refs/remotes/R/B with no warnings (I have even seen peers create and push refs/heads/refs/heads/R/B by mistake)
* the index should be a hidden implementation detail, with partial commits done instead via "git stash" so it's at least possible to test them (the index is also what caused "git checkout" and "git reset" to become bizarre grab bags of mutually exclusive actions)
I really need to sit down and write a blog post and set of aliases that let you use git-style branching in Mercurial through the bookmarks extension. It's completely possible, it's just not the standard.
The only thing I'm aware of that Git can do that Mercurial can't, branching-wise, is pushing deletes, which messes up everyone else's pulls anyway.
What about pushing only a subset of your branches? As far as I know, you can't commit to N branches and then push only a subset of them with hg.
There's also the whole index/staging area thing that I use everyday in git. That said, I think they're both alright. I think schacon summed it up pretty well in his talk at pycon:
I prefer git over hg because of its branch model. hg's doesn't compete, and git has totally changed my workflow with branches. hg seems like it would cause me to revert to the old way which is not desirable to me.
hg also requires extensions to do many things that git does out of the box (like the equivalent of git stash, which I also use often). I saw very little reason to prefer hg for the brief time I experimented with it.
In theory, you can use git's branching model, but in practice, it is preetty horrible in my experience (I have only one year experience with hg, though).
The tip thing mentioned by Armin is a big UI wart when using "intree" branches, by which I mean any branching scheme not based on cloning. It is also pretty difficult to name branches in the various commands - as far as I know, you cannot easily diff between two names branches, for example.
Nevertheless, I miss index much more than git's branching when using hg at work.
I'm going off of a brief time I experimented with it, I admit that I didn't use hg very long. I may come to like it better or learn more if I use hg for a serious project, though I know of no reason to do so voluntarily other than curiosity and education.
The branch model doesn't compete because branches are ingrained, as this article discusses; the changeset always carries the branch name with it. Branches are also ingrained as "long-lived branches" and instead of the mere application of a label to divergent changesets, these branches appear tightly coupled and are meant to be merged and/or closed in the way hg expects. You can only get git-like flexibility such as cherry-picking by making another clone or by installing a variety of extensions.
See http://mercurial.selenic.com/wiki/GitConcepts#Branch_model , which explains that git-like branches don't have a direct equivalent in Mercurial unless you use the BookmarkExtension to apply names to a changeset; otherwise, you must use hg heads, which doesn't work in quite the same way, at least during my brief experience.
On top of this, git is usually faster and usually has much smaller repositories (see https://git.wiki.kernel.org/index.php/GitBenchmarks), so I don't see much reason to prefer hg. git integrates fine with Windows if one installs msysgit, which includes a minimalist cygwinish environment and is not at all unreasonable.
I think that extensions are sort of badly named in mercurial, but you're making them out to be much more difficult to work with/install than they actually are.
Mercurial ships with a bunch of features ("extensions") turned off by default so that beginner users aren't confused with stuff before they're ready. Turning the bookmark extension on is as easy as putting "bookmarks=" in your ~/.hgrc file. So the bookmark branching model, which is equivalent to the git branching model and something I use every day, is a built-in part of mercurial. You just have to enable it to work that way.
The "transplant" extension (similar to cherry picking in git) also comes with mercurial and is just a one liner in a config file to enable.
So hg branches should behave like completely separate clones/repos that happen to live within the same folder/URL. That would fix pretty much all issues and be completely straight-forward since it mimics the separate-clones-as-branches model originally promoted by hg, with the difference that you don't have separate folders for the clones.