I was recently offered a review copy of Instant Mercurial Distributed SCM Essentials How-to, presumably because I’m vocal about Mercurial being my backup DVCS of choice. Or something. So I worked my way through its 51 pages looking to fill in some gaps in my knowledge of Mercurial.
The book is arranged as a series of ten recipes along the natural path through learning a DVCS: installation, local workflow, remote workflow/collaboration, and some extras. The book also includes recipes on setting up mercurial-server, both using a file share and using SSH, and an introduction to Continuous Integration.
Though I was already familiar with DVCS concepts and Mercurial’s implementation, I did learn a few things:
- Mercurial’s templates seem more complete and easier to read/use than Git’s pretty format codes
- Similar to PowerShell’s handling of arguments, Mercurial will execute commands as long as you type enough characters for it to figure out what you mean (
st => status,
out => outgoing,
in => incoming, etc). This works for aliases, too.
- Mercurial’s counterpart to a Git
--barerepository is created with the
- I knew Mercurial’s branches are heavier than Git’s, but I didn’t realize you actually had to close a branch (with
hg commit --close-branch) after its changes have been merged.
- TortoiseHg has a
shelvecommand that’s similar to
git stash. It turns out there’s also a shelve extension apart from TortoiseHg, which the book does not mention.
- Mercurial Queues are ridiculous. More on that later.
- The Crecord extension allows you to mimic
git add --patch.
It is very similar to the use of Git’s staging area…except that you have the choice to use it (by typing
hg crecord) or to commit everything (by typing
N.B. The more I use it and teach it, the more I appreciate Git’s staging area. Crecord captures only a portion of its capabilities.
The overall structure of the book could work well, but I was disappointed by the execution within some important recipes. Each recipe is broken into sections: Getting Ready, How to do it, How it works, and There’s more. The recipe itself is a numbered list within How to do it, which is where things get confusing: new concepts are often introduced partway through a list, without fanfare or sufficient detail.
For example, branches were introduced in bullet #7 (of 9) in the “Branching, merging and managing conflicts” recipe. Then There’s more concludes the chapter with a two-sentence paragraph introducing Bookmarks, which “offer another way of diverging to postpone the problems of merges and conflicts,” and giving this guidance on how one should handle divergent lines of work:
To summarize, for topical temporary diversion, it is a good practice to use only clones. It helps, for switching back and forth between several lines of development in parallel, to use bookmarks; and if you need a long-term diversion, use branches.
Maybe this is enough of the Essentials for someone new to Mercurial, but I was expecting more.
My other frustration was the book’s regular use of new commands and options without any introduction or explanation. I knew enough to guess at most of them, but I found the started purpose of a particular example was often lost in my need to process the unexpected new information at the same time.
The Using additional commands and extensions recipe includes a discussion of Mercurial Queues. I was looking forward to the “Essential” introduction to MQ, because the GitConcepts section of the Mercurial documentation says:
I rather like the index, especially now that I know how
reset works (and that it supports
--patch!), so I was curious what MQ brings to the table. In a word: confusion.
hg qinitcreates a file structure under
.hg/patcheswith its own Mercurial repository, so patches can themselves be versioned (which seems really weird to me).
hg qnewcreates a new patch, which seems like a “future commit” of sorts.
hg qrefreshapplies current changes to the latest patch.
hg statushere shows no changes, as expected.
hg log -r tiphere shows a new changeset, with a tag for the patch plus
tip. So it seems like this is kind of a commit, it’s just not referenced by any branches/bookmarks. Apparently
tipis always the most recent changeset, even if it’s not a real commit? I’m not convinced this is a useful distinction.
hg qcommitcreates a commit within the
.hg/patchesrepository to save the patch changes.
hq qappliedlists patches applied since the last real commit.
hg qpop, treating patches as a stack, removes one or more patches from the working directory.
hg qpushrestores one or more patches to the working directory – it’s unclear what happens if you fail to
- The book stops there, but apparently there’s also a
qfinishto convert a patch into a permanent changeset.
Eight new commands with no apparent relationship to existing Hg concepts. I’ll give MQ proponents the benefit of the doubt that it can be productive, but I’m not sure how it would fit into a complete workflow with branches or bookmarks. From what I know so far, it seems like a lot of effort to make mutable commits that aren’t commits, when it would be much easier to just accept that a commit doesn’t need to be immutable until future work depends on it.
Ultimately, this isn’t really my kind of book — as a professional, I like to know my tools beyond just the “Essentials.” If you’re looking for a bare-minimum introduction, with a little extra, this isn’t a bad place to start, though I would be surprised if there weren’t free material online of similar quality.