http://lkml.iu.edu/hypermail/linux/kernel/0504.2/0670.html
We will also be celebrating Mercurial's 10th anniversary next week during the 3.4 Pycon sprint:
http://lkml.iu.edu/hypermail/linux/kernel/0504.2/0670.html
We will also be celebrating Mercurial's 10th anniversary next week during the 3.4 Pycon sprint:
Git is an entirely appropriate tool for managing as something as large and complex as the Linux kernel, but I'm doing much simpler stuff, and Mercurial is simpler and has a much shallower learning curve. I'd recommend it unequivocally to teams of modest size working on average applications.
The state of git documentation is much better today than it was five or six years ago, so maybe its complexity is less of a big deal, but so far I've not encountered any issues with Mercurial that make me think "If only I was using git this would be easy!"
What I found with git was I had to maintain a fairly complex mental model of the current state of affairs, and because I'm not very intelligent that took quite a bit of effort. With Mercurial the model is much simpler, so I can spend more of my very limited attention on writing code. It's quite possible that I simply never took the time to learn git properly, but with Mercurial I didn't have to.
I really do feel like Git is appropriate for small projects. The .git store is incredibly small (because it only stores changes) and quite simple when you get used to it. You will only only need to use a tiny subset of Git's functionality (or, heck, just the Github web-UI if you wish).
I think the hardest thing about Git for big and small teams is getting used to the mental model of Git (branching, merging, master, etc). Once you get it down you realise that Git is less complex, not more...
PS - This comment is mostly in reply to the implication that Git is a better tool for large and complex projects like the Linux Kernel.
PPS - Mercurial might be a better tool yet still for small projects, I don't know enough about Mercurial to have a qualified opinion either way.
1. Local branches
Git has them, mercurial doesn't really. Mercurial wants you to use a lightweight clone (copy-on-write with hard links) instead. Lots of mercurial extensions deal with this however.
The lack of rebase in stock hg is probably directly driven by the lack of local branches that don't get pushed upstream by default.
2. Committing code
Mercurial, without extensions, doesn't have the git shelf. With extensions there's a few competing options like MQ, Shelve or Evolve.
Both these points make hg easier to learn (branch == clone is very easy to wrap your head around, commit behaves basically like svn/cvs).
It's also worth pointing out that many of the extensions you referred to (rebase, shelve) are bundled with core Mercurial and need only a one-line addition to a configuration file to turn them on. Extensions bundled with core Mercurial have the same level support and backward compatibility guarantees as the rest of Mercurial. Part of Mercurial's command line philosophy is to not include obvious foot-guns (like the ability to rewrite history) in the default version.
You can make a named branch and make it private so that it wont be pushed automatically or you can create a bookmark and mark the changeset as private, so that it wont get pushed automatically OR you can create a local clone, completely isolated from the origin repo.
The difference between git branches and Mercurial branches is a bit of a conceptual one. Git has 'user' branches, where a branch corresponds to the work of a user. Mercurial has 'feature' branches, where each named branch (is supposed to) correspond to a feature. I think This is the one of the reasons some Git users are sometimes so turned off when they see Mercurial branching model. And to me, I would like a project as a sum of its feature branches. But I can imagine why this might not be optimal for a something like Linux kernel. But for most projects, I think feature branches are more valuable than the user branchs of git.
>Mercurial, without extensions, doesn't have the git shelf.
Shelve extension is bundled, enabling is just a matter of turning on a flag in the .hgrc configuration file...
Er. Not really, no. Git is simply agnostic about how you use branches, and allows you to separate how published branches and your local branches are used implicitly. I've rarely worked on a multi-user git project where published branches corresponded to a user's work. Almost always they are feature branches worked on alone or with someone else.
Even in linux development, where the repositories are directly tied to users usually, the actual branches generally represent a work-unit of some sort, so I'm not sure where you got this idea.
If you mean the idea in the GGP's post that branches represent a user's work, again I think that conflates repositories with branches. It's not exactly impossible to find people doing work on master of their fork against an OSS project, but best practices (and common practice among most regular contributors I've seen) seem to angle towards using feature branches even then (and asking with a PR to merge eg. stormbrew/blah:fix-the-thing to upstream/blah:master).
http://fossil-scm.org/xfer/doc/trunk/www/fossil-v-git.wiki
Please see the Table on the top and the 'Branches' section.
You may be taking too strong a meaning of the 'ownership' concepts described there (and I think they're stated too strongly). No one owns a branch name in git, not even the person who first makes it. You own the branches in your own local repository, and you can choose how and if you share them, but it is perfectly possible to do shared work on a branch if you have a shared repo to work from (and even, with some extra work, without one).
This is basically a Zooko's triangle[1] problem, where git has chosen decentralized and meaningful, which necessarily implies a rejection of ownership (even to the extent that Fossil wiki page implies).
But in the end, most branches in git are focused on a piece of work and not who made them (it's mostly the 'lieutenants' in the linux model who would have personal branches). Single-author branches may be more common in git because it definitely does make those easier than other possibilities, but there is nothing stopping collaboration on a shared branch in git.
Local branches are really an artifact of Git having a garbage collector. That means that any commit that you want to keep must be attached to a branch so that it may not be inadvertently lost. Without a garbage collector, that is not necessary.
In particular, in many other VCSs, you just simply commit without having to create a branch in the first place. Labeling them (via whichever mechanisms your VCS provides) is typically optional with modern version control systems.
You can argue that you prefer having a garbage collector over having to explicitly delete commits/branches that you do not want any longer, but that would be a different issue.
> 2. Mercurial, without extensions, doesn't have the git shelf.
This is sort of incorrect -- or rather, probably a misunderstanding. Shelve is part of standard Mercurial and has been for a while (same goes for MQ). While it is disabled by default and enabled in the extensions section, it's no more an extension in any meaningful sense of the word than git stash (which technically calls out to a shell script [1]). Mercurial's shelf is a python module [2] that is loaded when you flip a switch.
> Both these points make hg easier to learn (branch == clone is very easy to wrap your head around, commit behaves basically like svn/cvs).
This is really more a feature of Bazaar, not Mercurial.
[1] https://github.com/git/git/blob/master/git-stash.sh
[2] http://selenic.com/repo/hg-stable/file/default/hgext/shelve....
Since, for me, local branches are a massive part of why I prefer git, I'd be interested in examples of how to do the same thing in other VCSs.
It doesn't make sense to me that they're a byproduct of having a garbage collector, since (1) git-stash exists, (2) local branches are a common selling point, and (3) git-clean honestly seems tacked on rather than a core piece of the design.
By default, it doesn't have a special name (like a git branch does). You can give it a name via "hg bookmark".
The feature set is honestly fairly similar, it's just different in the way it is presented. In git you go into a "detached HEAD" and have to explicitly name a branch or commits will get lost. In hg you commit and it creates a new tip, but it doesn't have a name unless you explicitly name it via bookmark.
Maybe I'm missing something, but this seems like a fairly academical scenario.
When would you checkout a specific commit, keep working, keep committing, but not attach it to a name or a branch? How is "67846237864237846" a nicer reference than "bugfix" or whatever?
To me this seems like people using git in a way it's specifically designed not to support and then go complaining when things go wrong.
You enter a commit message when you make a commit, right? So I am not sure I see your point..
- Commit 1 -> Commit 2 -> Commit 3 (master/default) - current branch
Now Commit 3 is the HEAD of your current branch (master, trunk, default, whatever). The way I understand your "problem" is if you want to create a new branch based on an older, non-HEAD commit.For instance you checkout the current branch on based on the state of the branch as per "Commit 2", and make a new Commit "Commit 4". This creates a new implicit branch:
- Commit 1 -> Commit 2 +-> Commit 3 (master/default)
+-> Commit 4 (implicit branch) - new current branch
Now you have two branches. How do you switch between them? How do you operate on those branches? Do you cycle them? Do you have to remember the last commit-message of a branch to find it again?To be absolutely clear: What I'm curious about is how do you relate to and navigate between branches when they are all anonymous? What mechanisms do you have to aid identification?
But say, you forget to merge it or didn't bookmark it, Mercurial does not hide the revision from you. The hg log will list it along with all the other commits.
Even easier is to use the hg heads command, which will show all branch heads for you (Branch heads are change sets that have no descendants on the same branch), along with the commit summaries. You can use the commit summary to select the revision and use a revision id (You don't have to use the full length hash, instead you can use a 4 or 5 character prefix of the revision id) to switch to that commit.
To me Git is clear and simple. It's a linked commit-graph, and branches and tags are just references to leaf nodes on the graph. That's all. That's the entire model.
With hg you have local commit IDs, you have revsets, you have bookmarks, and then since you aren't forced to name a graph/branch you have to remember commit-IDs or who did what when to what file. Some commits show up on the commit-log, but you can't be sure if it's in the current branch. I'm totally confused as to what to use where and how I can be certain about what I'm working with.
I'm not saying hg is bad per se, but looking at it from the outside it looks helluva more complex than Git. I think this all boils down to what you're used to.
From the discussion in this thread here, I'm pretty certain I wont be trying mercurial anytime soon. It just seems too complex and confusing for me ;)
Same in Mercurial. But it lets you store a bit more meta data (Bookmarks, branch names, local revision numbers etc) which enables more powerful queries based on them. I am not sure that is a bad thing. But I can certainly understand why it appears complex to when presented with all these information at once.
But trust me, when you are trying to make sense of what went wrong with a merge done by an in experienced co-worker, you want all the metadata you can get..
>and then since you aren't forced to name a graph/branch you have to remember commit-IDs or who did what when to what file. Some commits show up on the commit-log, but you can't be sure if it's in the current branch.
Now you are talking FUD, no offence.
>you have to remember commit-IDs...
??, I just told you how to manage such cases. Which part you didn't get? In Git you would have to dig up reflogs for the commit hash for a' DETACHED HEAD' that you just made, Right?
>Some commits show up on the commit-log, but you can't be sure if it's in the current branch.
Not sure what you mean by there or where you got that idea. Every commit you make will be displayed by the hg log, regardless of the branch it is on. If you want to filter log by a branch, there is a -b option accepts branch name as an argument, that you can use to limit the display to changesets in that branch only.
>From the discussion in this thread here, I'm pretty certain I wont be trying mercurial anytime soon. It just seems too complex and confusing for me ;)
If Mercurial was actually 'complex and confusing' it would have been dead a long time ago (Thanks to git). The simple fact that it survives (and even grows in popularity) despite git, IMHO is a sure sign of how simple/straightforward it actually is for common things. So do yourself a favor and try it sometimes. You just might like it.
So in your example you would do:
"hg update 2" to checkout Commit 3, and "hg update 3" to checkout Commit 4
Note that these revision numbers are _local_ to your repository. That is, another clone of the same repository may have different revision numbers assigned to different revisions. The revision numbers are assigned in the order in which commits have been added to that particular clone.
You could of course also use the revision id (i.e. the SHA1 hash) to identify them. You do not need to use the whole revision id, just the part that makes it unique, usually the first few (e.g. 6-8) characters of the hash.
In addition Mercurial has a very rich mini-language to query and identify revisions in your repository. These queries are called "revsets". Most mercurial commands accept revsets wherever they would need to receive a revision identifier. With it you can identify revisions in many ways such as by date, by belonging to a given branch, commited by a certain author, containing a certain file, etc (and any combination of those and many others).
Finally, if you use a good mercurial GUI (such as TortoiseHg) the whole thing is moot because the GUI will show you the whole DAG and you can just click on the revision that you want and click the "Update" button.
I actually find the ability to create these "anonymous" branches really useful. Naming things is hard so I find that coming up with a name for each new short lived branch is annoying.
No, you aren't missing anything. I merely used the example to illustrate the difference between the two VCS's. Like I said: they actually have a fairly equivalent set of features. The prime user-visible difference is in interface and implementation.
You simply commit a new changeset based on the desired parent. The branch would be created implicitly by having a revision with two or more children. It does not have to carry a name; naming revisions (or sets of revisions) is an orthogonal concept for the purpose of navigating the revision DAG [1], whereas in Git branches have the additional purpose of keeping revisions from being GCed. Any revision that is not referenced by a ref (directly or indirectly) will eventually be GCed (once it is removed from the reflog and the grace period has expired).
> It doesn't make sense to me that they're a byproduct of having a garbage collector
It is a byproduct. Because if you did the above in Git (which Git won't let you without being explicit about it, but it's possible), then one or the other child would get GCed sooner or later. That's because there's only one HEAD commit, and that can prevent only one child from being GCed, so you have to create a ref to the other (generally via a branch) to keep it alive.
> since (1) git-stash exists [...] and (3) git-clean honestly seems tacked on rather than a core piece of the design.
This has nothing to do with git stash or git clean. I'm talking about one of Git's architectural principles, where the repository is essentially a purely [2] functional data structure and revisions that are not reachable from one of the roots (refs/branches) are subject to garbage collection.
[1] And if you look (aside from Mercurial) at Bazaar, Fossil, Monotone, or Veracity, you'll find that there are multiple ways to go about that.
[2] Well, not entirely pure, but close enough.
Not only that, but it is also used to decide what all commits to show to the user. In that way branch names act as little windows through which you can look at the DAG of history. Commits that you cannot see through this window does not really belong in the history according to git, and will be GC'ed.
So if you make a commit on top of a revision that is not a branch head, then it becomes a DETACHED HEAD. Actually there is nothing 'detached' about it. It is linked to the parent commit just fine. But git just does not consider it part of the history unless you give it a name. Here you can see the problem with git naming. 'DETACHED HEAD'. If you understand a head revision as a last revision in a sequence of connected commits, how can there be a 'DETACHED HEAD' when a 'HEAD', by definition is part of a sequence of commits..
I wonder why someone would call it a 'DETACHED HEAD' instead of something like 'UNNAMED HEAD' or 'ANONYMOUS HEAD'....
And then, how do you later track these commits? How do you change or merge branches if they have no names? Do you go around remembering revision-IDs?
I'm not trying to be judgemental and say this is wrong or anything, but I'm curious how this works out in practice.
My own preferred approach is to use hg share, which allows me to have multiple checkouts of the same repository, each with a different current revision (HEAD in Git parlance). This is because when I'm doing some local branching, I generally like to have two different sets of files to work with (so as not having to rebuild when switching back and forth, being able to easily run side-by-side comparisons, etc.). This is sort of like Git's git-new-workdir, except that git-new-workdir isn't safe; it is also the default mode of operation of pretty much any DVCS other than Git and Mercurial. This, I note, is not necessarily what the majority of Mercurial users do -- especially since this feature first has to be switched on --, but is one of the major reasons why, if I have to pick either Git or Mercurial, I'll generally go with Mercurial. Multiple checkouts are simply too important a feature for me to want to deal with Git's workarounds; Mercurial's support of them is imperfect, but still better than what Git has.
More commonly, in Mercurial you will simply not need to name temporary branches. You will have named branches for your major features etc., and you can use hg heads -r <branch> to list the 1-3 heads you may at any time have per major branch. This makes naming the heads sort of superfluous for typical development. Also, if you have only two heads in a branch, hg merge and hg rebase will automatically pick the other head to merge/rebase against.
Alternatively, you can use bookmarks. Bookmarks are essentially like Git branches in that they are pointers to commits.
Finally, there's also nothing inherently wrong with simply using named branches, even for temporary work. It's up to you or your organization whether you want persistent or temporary names for temporary work.
> The .git store is incredibly small (because it only
> stores changes)
git stores a complete copy of each revision, not changesets. (Well, it is my understanding that a .pack compressed archive of objects may store some of the objects as changesets, but that's not the general case)What it doesn't do is store files as deltas explicitly against the previous or next revision of that file. It attempts to find a best fit dynamically.
It also does something like this packing procedure when responding to a fetch to avoid sending more data than it needs to, btw.
[1] https://www.kernel.org/pub/software/scm/git/docs/git-repack....
Essentially it is not line level, but file level, rather than complete repository level (e.g. like Team Foundation is).
And you can tell from how the product is being used. Where I work, we use TFS and you literally need to have committee meetings before a new branch is made.
You need to agree on long term strategies, you need to agree on branch hierarchy (because TFS cannot merge without one), you need to replicate all-the-things(tm) for your new branch, you need to adjust your versioning-strategy for this branch, and possibly future branches which may come and may not ever collide with this one, because TFS branches are massive and carved in stone. They are forever. Etc etc.
You never branch more than once a year. In the world of TFS, doing such would be madness, haphazard. Or at least you would need a full team doing nothing but branching and merging and integration. And good luck trying to find qualified people willing to have that as their day-job.
With git you branch every single time it makes sense, usually several times a day. And your life is nicer because of it.
It's funny how such technical decisions results in such huge and enormous visible changes to how a product is being used.
Somewhere deep in Microsoft there are probably one or more engineers crying right now seeing the effects of their (back then) seemingly innocent decision, as they themselves are forced to deal with TFS in their daily work and they see how nice the gitters have it.
It took me about a year to realize how bad it really is: eventually I found my way to a "how to create a dev branch" document starting with:
"Last year Dev Wossname wrote a useful mail showing how to create a dev branch and got most of the details right :-) This howto explains it in more detail and fixes a few points."
Then followed a quite few pages with a dozen manual actions doing somewhat intimate things to levels of P4 I had not previously heard of...
Oh, and it created the branch at the *company-wide root level*, e.g. `gmail/` -> `gmail_dev_branch_2012/`. No pressure !-)
It then took a few more days until the horror of that opening sentence sunk in. Native large-scale branching was so rare that it was almost a lost art![There were also several "lightweight" branch-like techniques based on symlink magic, FUSE filesystems and more magic. Those were routinely used for freezing a release build, with option to hot-patch it — but IIRC it was impossible to merge back onto the main tree.]
In practice things weren't that bad because (A) Google got really good flow (especially continuous testing) for everybody working close to HEAD, (B) personal branches were easy and common:
- Fresh checkout directories were cheap [should have been frightfully expensive but clever scripts and a FUSE filesystem fixed that]. - Every CL (commit progressing through code review iterations) was effectively a feature branch. - People who wanted more used a somewhat crazy, but very workable, internal tool mirroring a growable {time,space} subset of P4 into local a git repo and back onto P4.
Subversion mostly copied the way p4 did it, but without the view control stuff (where there's a server-registered and quasi-versioned description of what local file paths map to what server paths) that perforce has/had.
One correction: Git does not store changes at all. It stores all the versions of files as separate "blobs". What keeps .git small, is that Git compresses the object database to pack-files. "git gc" does this for you.
Pro Git has a great chapter about how Gits internals work: https://git-scm.herokuapp.com/book/en/v2/Git-Internals-Plumb...
This picture sums the model nicely: https://git-scm.herokuapp.com/book/en/v2/book/10-git-interna...
For me studying Git internals has been a good lesson in software design. Git's core is very simple, yet somehow that makes it a really versatile tool.
Going into a directory and easily creating a repo there, where I need it, is great.
Canonical did something similar with their Bazaar tool.
http://www.selenic.com/hg/help/revsets
I have tried to switch to git multiple times. Every time, I keep coming back to Mercurial. The most difficulty I have with git is the non nonsensical naming of concepts. For eg, A branch is a pointer to a commit. Because of this, I experience a big mental block when I try to reason about something. With Mercurial this is very much easier. And if you are using a DVCS to any capacity you ll have to do this often.
Another great thing about Mercurial is how easy to get help about stuff. You can head to the IRC chat room and can have a very good chance of catching one of the developers who, in my experience, were very helpful...
Revsets together with templates can be used to build custom commands:
http://jordi.inversethought.com/blog/customising-mercurial-l...
There are also filesets that work similarly for doing queries on files (hg help filesets).
This is a frustrating thing about how people tend to talk negatively about git. I think what you mean is "not named in a way I'm used to," because there's nothing nonsensical about this naming at all, and it's actually an incredibly simple and lightweight way to reason about naming things in version control (imo, I suppose). And it permeates basically every level of how git organizes information in a pretty darn uniform way.
To me mercurial's two kinds of built-in branches and several plugins to do branch-like things is much more complex, but I still wouldn't call it nonsensical. That'd just be admitting that I stopped thinking about it when it was strange and unfamiliar to me.
Of course, that is the whole point of naming something sensibility..Just, for example, imagine how hard it would be if you have to learn/work in a version of C that calls pointers as 'branches'.
>To me Mercurial's two kinds of built-in branches and several plugins to do branch-like things is much more complex, but I still wouldn't call it nonsensical.
I don't know what you mean by 'several plugins to do branch like things'. Isn't it more frustrating that people complain about a tool because they have to enable some advanced stuff by configuration. But I agree that Mercurial is actually complex than Git, because it provides more options to the user. So the complexity of Mercurial is a side effect of it being more powerful IMHO.
So the point is I say, naming a 'pointer to a commit' as branch, is nonsensical because it goes against our notion of the word 'Branch' from real life. It adds unnecessary burden for a human being trying to think in the language of the tool, without actually making the tool more powerful. Git could have been as powerful as it is now even if it had named things better, Right?
Yes, if you rename <arbitrary thing> to <other arbitrary thing>, it is very likely to result in nonsense. This is not such a case.
A branch in git is literally a name for a branch of the DAG that is the commit tree. It's possibly the least abstract interpretation of the concept as possible. There is nothing nonsensical about it.
But the objection seems to be that you don't work with it like in svn or hg or p4 or cvs (which are also all different from each other), which does not make it nonsensical, merely unfamiliar. This is the distinction I'm driving at.
The objection is that, when naming is skewed in lower levels it makes it harder to reason about higher level concepts and creates ambiguity..
For example, let us continue with the idea of a 'branch'...
Suppose you define a branch as 'a set of commits'. Then it is easy to imagine a 'remove' operation on a 'branch' will remove all the commits in that 'branch'. There is no ambiguity.
But when you define a branch as 'a pointer to the last commit in a consecutive set of commits', a 'remove' operation on a branch is no longer clear what it is supposed to do.
Does it simply deletes the pointer, in which case the commits will remain untouched? But it would not be consistent with the abstraction of the 'branch'.
Does it remove all the child commits from the history? by which the operation would be consistent with the abstraction of a 'branch'.
Now the remove operation is ambiguous as to what it actually does.
Note that there would be no ambiguity if the user does not know that a branch is actually a pointer to a commit. Because git hides all the change-sets that are not the decedents of a branch. So a users concept of a 'branch removal' is maintained. But I think it is pretty accepted that using git requires that you know stuff like these...
So another way of looking at the problem is that, Git forces the user to work at multiple levels of abstraction simultaneously. And this creates ambiguity because the user wouldn't know which level of abstraction to use when reasoning about something, and defeats the whole point of having abstractions in the first place IMHO.
The problem is not with Git's use of pointers, but with your own thinking.
One should not be able to "remove" commits, because any operation should be undo-able. In git removing commits implies updating a pointer. And if those commits end up not being referenced by anything else, then they'll get garbage collected. What git does is very close to how persistent data-structures work. And many people complain about it just because it's unfamiliar.
And in your example, of course there's ambiguity, how can it not be? What happens with the branches that are forked from your branch? That's the definition of ambiguity right there.
> So another way of looking at the problem is that, Git forces the user to work at multiple levels of abstraction simultaneously.
In my experience, the problem with Git is that people don't bother to read documentation for a tool that they are using every day.
Care to elaborate? Do you mean when removing a branch, what happens to forked/child branches? There is no ambiguity, a change set cannot exist without it's parent or cannot be moved to a different parent without changing its identity. (The revision hash is a function of its ancestors too). So if you remove a branch, the forks/child branches will be removed as well.
Anyway, that was just a made up example to show how naming can affect reasoning. I don't think Mercurial or Git allows you to delete branches directly....
Of course, if you delete a branch and then run git prune, its commits should disappear as long as they weren't part of another branch.
Git branches are pointers to commits. For example I can move the pointer to a commit to point to the previous commit instead. But the commit which was previously being pointed to is still there. However when I say that I reset a branch to a previous commit, I get the feeling that the branch was "cut", and so that the commit was lost - which is not the case.
This is why using the name "bookmark" is better in my opinion. Not because I'm used to it (I've used git much more than mercurial), but because it's a better representation of what is actually happening.
Note that the technical name for branches in git is refs or references, which more accurately describe their nature.
Maybe his knowledge of Mercurial is 5+ years old. In versions before 1.8 (2010 and before), bookmarks was an extension ("module") and you had to add a line in .hgrc to take it into use.
Even some of the Mercurial developers does not like Mq extension much...
Git was not named with Mercurial in mind. That's what they're saying, Git's naming only feels strange because you're coming from another VCS. I found Git's naming strange wen I came to it from SVN. When I tried Mercurial after that, I found it's naming strange. Everyone names things differently. It's not a Git issue.
Personally, I much prefer git, and I researched both before I used either. But I wouldn't fault someone for preferring mercurial, particularly if part of the reason was that they were very comfortable using it.
FYI, "e.g." stands for "exempli gratia" which is Latin for "For the sake of example".
So "for eg" is actually "for for the sake of example".
I started using Mercurial because the basic interface and operations appeared more natural to me. Also, at least at the time, the Windows support was better in Mercurial.
After working with some repos using Git, I fell in love with the staging area, and the ability to selectively stage parts of files. I am sure Mercurial has something similar, but it was built into Git.
The only thing that bugs me is that the Windows port appears to be stuck at 1.9.5 (yes, I know it's open-source so I should go fix it instead of complaining).
What? What gave you that impression? That's a really old version. Here's the last 3.3 Windows build:
http://bitbucket.org/tortoisehg/files/downloads/tortoisehg-3...
This was from the downloads page:
http://mercurial.selenic.com/downloads
Edit: Oh, crap, I completely misread that. You were talking about the git Windows version. Oh well. Mercurial Windows versions are staying quite up-to-date, thanks to the tireless work of Steve Borho.
https://bitbucket.org/edgimar/crecord/overview
If you want a "staging area" just use a temporary commit and keep ammending it with `hg crecord --amend`. There really is no difference between a commit and a staging area except the name. If you're afraid of pushing your WIP commit, use `hg crecord --secret` or `hg commit --secret` so that your commit will be in the secret phase and won't be pushed until you declare it draft with `hg phase --draft`.