Hg Init: a Mercurial tutorial by Joel Spolsky
hginit.com
hginit.com
FWIW, try to give a few DVCS tools a shot before settling on one.
I was a big hg fan, and really didn't care to switch when my coworkers ganged up on me and decided that git was a better tool, but I think they were right.
The git command line leaves much t be desired; hg was far more intuitive. But I would occasionally have merging issues with hg that were just too annoying (lost or missing file changes, for example) that I haven't had with git.
But that's anecdotal, and I'm sure (if you follow enough dvcs flame/troll threads :)) you'll hear other stories about other tools. The upshot is to try a few to see which works best for your particular needs.
There are scenarios where Git reverts some changes unexpectedly and almost silently, if you don't take care. In contrast, Mercurial's strict "every merge is an explicit commit" principle saved me from a lot of problems.
Regarding the command line interface: Darcs has still the best one. Well, Darcs has some performance issues, but its interactive dialog-based command line interface is outstanding. It is years old, but neither Mecurial nor Git come even close to it.
So if you have a small project or a fast computer, you should definitely have a look at Darcs in addition to Mercurial and Git.
The reason I'm switching is because I like the tools better, and you can be up and running with a repo in about 5 seconds. I think that's argument enough. There's less pain.
But what is so different about merging in hg/git that merging a complex change from a branch is somehow made magically trivial? I mean, the tools for handling changes might be better because they are more modern, but the whole "changeset" thing seems to be hyperbole -- all (well, any good one) VCS's track changesets, that's what those revision numbers (or collectison of rev numbers) mean. :-)
I understand where you are coming from. I used to think the same way. But once you have used git or Mercurial with their powerful branching/merging capabilities, you will never go back to anything else. Also, it's not that the tools aren't better, it's that git and Mercurial have different architecture which makes branching/merging easy and powerful. I would sincerely request you to not dismiss this 'branch/merge' phenomena. Once you understand their power, you would wonder why you ever managed to live with Subversion (or other centralized VCS).
Searching on Google, I came across this example which will show you how powerful Git really is. [warning: PDF link]
http://ietl.univ-lyon2.fr/sites/ietl/IMG/pdf/Git_merging_by_...
The difference is that hg preserves the local commits as part of the upstream commit-set. That gives it a lot of information when making decisions about merging. SVN only has two versions of the file: what's in the server and yours. There's just less information to merge intelligently.
My guess is that there is some intelligence that can tell that "foo missing there, and foo added here" is actually just "foo moved from there to here", unlike SVN, which attempts no such heuristics. I hope someone can correct me if I'm wrong here :)
The end result is that when you have two branches that have become even a little out of sync with each other when you try to merge them together SVN doesn't know what to do because all it can do is diff one version against the other. Imagine how this looks if you've spent a bunch of time refactoring in one branch, moving code around, deleting code, adding new code, etc. The end result is that you basically have to hand-edit each file into the final merge state you need it to be in, entirely defeating the very reason you use source control tooling in the first place. You might as well just print out all the code from each branch and get a committee to merge it all together using scissors and craft glue, it wouldn't take any longer or be any more onerous than it would be using SVN.
In contrast, more sophisticated VCSes, including hg, keep track of changesets, and they are capable of tracking those changesets as they move through different branches. When you merge in Mercurial it's able to trace through the revision history of a file in the source and target branches, find the common revision, then separately apply the diffs from the source and target branches, automatically check for conflicts (e.g. changes from both sides that touch the same blocks of code) and create a sanely merged final result which will only be flagged as a merge conflict requiring manual intervention when there's a high probability that there actually is a merge conflict. More so, the merge conflict will be presented in such a way that it's actually sensible, showing the actual conflicting changes and the resulting conflicting final versions of the file, making it fairly straightforward to resolve even in that case.
Casting this in the form of a real world example, consider a "main" branch with two dev. teams each working in their own child branches. For the most part each dev. team works on their own code within their own set of files, separate from the other team's, but there is some common code which both teams have a tendency to contribute to or change. Team A spends a bunch of time making changes in their own branch (branch A), committing as they go, then merges these changes up to main. Later team B merges their changes to main as well. Instead of running into a merge conflict nightmare that requires huge amounts of developer time be expended in sorting out the state of each and every file, the version control system sees that team B hasn't made any changes to most of the files in the repository, and most of the changes team B has made are to files that haven't been changed by anyone else, and there are only a tiny number of changes to files that had also been changed by team A's recent commits, which hadn't been merged to team B's branch before team A pushed their code up to main. However, most of those edits are to distinctly different parts of the shared files, and are automatically merged without human intervention, only a tiny handful of merges require manual intervention, a process that takes only a tiny number of people a few minutes to sort out. Some of those automated merges may, in theory, not be safe, but that is what testing is for, and the devs can still review and sanity check the merged files before committing if they like.
The ability to turn a show-stopping ordeal into a routine task can be utterly transformative to the development process. There are many big dev. shops that are reliant on dozens or perhaps hundreds of big merges (in multi-thousand file code bases) shuffling around code between various branches every day.
Originally subversion couldn't do this, but it has had merge tracking since version 1.5 (a couple of years already). You can now merge one branch into another multiple times without specifying explicitly which revisions to compare.
I have seen a number of people saying that the merge tracking in subversion still isn't as good as what's in git or mercurial, but I haven't found an explanation of the difference. Can someone elaborate, or point me to some good reading?
lallysingh and nollidge point out that in a DVCS model you tend to make more frequent commits, because committing and publishing are no longer the same action, and that having finer-grained commits makes automatic merging more likely to succeed. This seems quite plausible to me, but it's orthogonal to the problem of merge tracking (isn't it?).
EDIT: The above comment may seem negative but that's not the intention. As much as this site will help their SEO effort, I think the guide itself is awesome. I am a git user and when I was learning git, I went through similar 'examples' to understand git. I think this is the best way to learn git or hg!
EDIT: I wanted to mimic the guide for git at gitinit.com and someone has already registered it!
(Though if you're doing it for narrow SEO reasons, I might consider not breaking it into its own domain. Links pointing at it won't help the product rank if the product is on a domain different than the linkbait.)
As it happens I started moving to Mercurial yesterday, how is that for luck. I think the Hg site documentation is fine, but I have to say, Joel's is more fun right out the gate. May much Google juice flow his way.
Compare it to the normal dry, unreadable technical writing on similar subjects and it's just night and day.
http://mercurial.selenic.com/wiki/GitConcepts
It answered many of my questions on the nuances of Mercurial. The branch model, bare repositories, and command equivalence table were especially helpful for someone like myself who has used both systems but never fully understood the distinctions.
Is there an easy way to educate older and/or less technical IT professionals about source control? I haven't been able to do it myself, and I wish this was it.
http://betterexplained.com/articles/a-visual-guide-to-versio...
For IT people you should have your /etc/* files under revision control to track any changes and easily roll back changes that break your system. I actually think there are some tools that are specifically for this purpose and not the general purpose SVN/git/hg variety but I cannot think of them off the top of my head.
There's a free trial of the hosted version that you can sign up for at http://www.kilnhg.com/. Also, Kiln and FogBugz are both free for Students and Startups (2 users or less). Give it a shot and let us know what you think.
Cheap local branching: mercurial has had this since day one, and for a long time has had most of the capabilities mentioned in this section for a while. Unfortunately, it hasn't had good named branching support, so most mercurial users preferred to branch through cloning, but that was never necessary. Right now you can use bookmarks for temporary named branches but there's no built-in support for sharing them. You have to write your own extensions to copy bookmarks files around automatically or just do it manually. Mercurial really needs to deal with this, I think. It's the only feature I've seen in git that I wish mercurial had.
Staging area: mercurial has mq, which is far more powerful than a staging area. In all honesty, I only use mq as a staging area and ignore it's other features most of the time, and using mq only as a staging area is just as easy as using git's staging area. Also, not having a staging area forced on the user by default makes mercurial much easier to pick up than git initially, and later on if a user wants the same functionality he or she can get it.
github: Mercurial has bitbucket. Github is far more popular, but not necessarily technically superior as far as I know.
That puts mercurial almost entirely on par with git in terms of this web site's criteria.
edit: reading more carefully, http://whygitisbetterthanx.com/ doesn't actually claim mercurial doesn't have the features mentioned above. It does just claim that git does things better. They say their local branching is better(it is) and github's social atmosphere is better than competing products(it is). However, with mq and the record extension you can do the same things as with the staging area.
Coming from darcs to git (I add -p more or less exclusively), I didn't think I'd use rebase much but commit reordering/squashing has turned out to be very useful the few times I've wanted it. I know it's doable with mq, but you have to know to mq everything before the fact rather than after.
Another great resource is the official Git User Manual, which I didn't know existed until just the other day: http://www.kernel.org/pub/software/scm/git/docs/user-manual....
I am brand new to git and I've been pleasantly surprised at both how thorough and also how newbie-friendly the User Manual is.
The bigger question is: if you follow this tutorial and like Mercurial, why then use Git instead?
Haven't purchased it yet myself, but been meaning to.
http://www.pragprog.com/screencasts/v-jwsceasy/source-contro...
Late one night in the Kiln alpha period, though, I was hacking around the Mercurial integration, messed up, and suddenly realized that issuing "hg up" held the repository at its current version, but moved time itself to match the requested revision. In other words, I had unintentionally made a time machine out of Mercurial. After riding a dinosaur for awhile, it hit me that I suddenly had a chance to get Kiln a legitimate mascot.
I thought for awhile about where and when to go, then promptly "hg up"d to the mid 1600s. I went to the island of Mauritius, and approached the dodo bird. I explained that, through no fault of the poor bird, it was about to go extinct. But I had an option: I could "hg revert" the thing back into the present, restoring it from extinction, if only it'd be willing to sign an exclusive marketing contract for Kiln. We negotiated a little bit back and forth, but at the end of the day, as you can see, the dodo happily agreed. It now lives a life of luxury, and has even taken up recently to hanging around kiwi birds an awful lot.
Unfortunately, the current version of Kiln can only restore deleted files, not deleted species, but we still think the dodo--a peaceful bird with no natural enemies, restored to the present--makes a nice mascot.
E.g., take advantage of hg commit and related commands to try changes out on the local repository, and use svn to commit those changes to the central repository?
But if you read the subversion book, or any other good tutorials, you know that developers using svn can just as well make their own private branches
So under branches/ I can have bob/ sue/ alice/ and they can have copies of trunk (or other branches) to their hearts content.
So why is this a big "win" for Mercurial?
(Will read the other sections later, no time now)
* I can take my repository on the train/bus/wherever and still commit.
* If I'm working with someone who needs to use my 'buggy' code I can push just to their repository (or they can pull from mine).
* I can have my own workflow and create as many branches, checkouts, etc. as I need.
Of course, the example that he gives there is bizarre - effectively the Hg equivalent of hanging onto your code for 6 weeks and then merging all at once...
I think the main advantage is really for larger groups. Having 3000 branches in the linux repo would be unmanageable. Also, private branches are something SVN can't do to my knowledge. If I want to hack on a git repo without anyone knowing, it's easy.
But there's many advantages to GIT/Mercurial over SVN/* aside from the "everyone has a repo". I love git but currently use SVN due to legacy and keyword expansion at work and it's not that bad.
You are right. Svn can branch. Can. But branching in svn is always a dangerous proposition. There are a lot of mechanics involved with branching it right initially, making sure that branch is properly tracking Trunk (you have to constantly merge from Trunk down into the branch to hedge the bets on eventually merging that branch back into Trunk). Properly merging a big branch into Trunk is also an undertaking, and more importantly, it requires the whole team to know its happening and "Be careful checking stuff in for I AM MERGING".
Also branches in svn aren't private. Anyone can see them. They are private by convention sure.
So compare all that workflow with a DVCS. The branching is free. It happens all the time and you never notice it. The merging is smarter, because it has to be, and the history is more complete, because it has to be to enable the merging.
When you do consciously branch it's a quicker, more robust operation. Doing big scary feature branch merges isn't as scary since they're happening privately before you push back to the (culturally defined) central repo. Yes you still have to merge from "trunk" to branch in DVCS but, again, it's a baked in feature since thats how you pull changes from someone else (for example in git you fetch changes from the central repo into remotes/master and then merge them into your master. Same operation as merging master into feature branch, or branch into master).
Yes you can walk to San Francisco from New York. But you can also Fly.
That's the end of my rant. Obviously it's based on my experiences with these tools and not yours. Just trying to give some context and justification.
Sure, you can make "private" branches (not actually private) with SVN, but they're still on the server. That means:
1. You can't commit to them (or check out from them) when you're offline. 2. Commits, checkouts, diffs against older revisions, etc are slower when you are online. 3. Bisecting would be painful because of point 2. 4. You can't make a bunch of commits and fold/reorder them with something like the HistEdit extension because someone may have seen them.
If you're comparing SVN's revisions with Hg's changesets, still no dice, for the same reason: changesets are unique for a file, given that file's history, and the hash trail allows for a clear way to figure out where changes happened, and merge from that point. A SVN revision just tells you how many commits have happened up to that point.
This is a great read though, even if you already switched to git, because the two are so similar.
If you're intent on building from source, make sure you're running "sudo python setup.py install; sudo make install-doc". Installing with the makefile directly will place packages in /usr/local, where Python doesn't normally live under OS X.
For reference, mine is:
/usr/local/lib/python2.6/site-packages/:/System/Library/Frameworks/Python.framework/Versions/Current/lib/:
For a commercial product that needs to be integrated in the windows world like kiln I would have made the same decision that Joel did. (Though I prefer git overall)
(edit change link to the YCombinator discussion)
Oh, what a wonderful world that would be...
Edit: about performance, while Git was slower on windows than on linux, it was still faster than both SVN and Mercurial.
Git still doesn't work well on windows and it's damn slow and only 2 years old, also running it with cygwin was a pain because you had to install it manually and stuff. High 5 y'all!
/me disappointed by HN, expected better than reddit like users.
Where are you getting your performance results from? The footnote from Google's article[1] on choosing between Mercurial and git states that Hg was faster both over HTTP and when compared to git's wire protocol. But I'm willing to admit those numbers may be old, so is there a newer published benchmark anywhere?
Again though, I was curious if you had some numbers. I'm not here to argue which is better, because, really, it's a subjective argument.
Further, I am not exactly thrilled by the claim that it runs okay "as of fairly recently". There haven't been all that many changes over the last year. So you are obviously wrong. It is also a insult on our work, which you should be fairly ashamed of.
Ciao, Dscho
P.S.: what kind of "Hacker News" are shown on this site when you cannot even comment using w3m? WTF?
Second, it's like Python vs Ruby (Hg vs Git). Doesn't matter.
Third, any attempt to fix the current issues of programming is better than "just hire a super-human-developer and leave him alone". Spolsky pushed bug tracking systems couple years ago, now he's advertising code review and better code commit/build workflow.