The Stochastic Game

Ramblings of General Geekery

Posts tagged with mercurial

Vim and Mercurial

Edit: since the original publication, I added a paragraph on vim-signify and a few other little tips based on some #mercurial IRC feedback.

I already mentioned Vimwaysadvent blogging about Vim, but here’s some more commentary on one of their entry, namely the Vim and Git one. It was quite good so I figured I would write a “Vim and Mercurial” one!

Since Samuel (the original post’s author) did a good job with the overall article structure, I’m going to totally plagiarize it.

Read more...

Mercurial Advent Blogging

Here’s another advent blog series! This time it’s from Kamal Marhubi and it’s on the subject of Mercurial. It’s pretty interesting, especially for giving a fresh perspective on Mercurial’s user experience.

The introduction post lays down some of what makes Mercurial interesting (phases, changeset evolution, extensibility) while the third post catches up to another cool thing (revsets, one of my favourite Mercurial features) that was missing from that initial list.

Extensions and papercuts

There’s a good article in the series about how Mercurial’s reliance on extensions (and more specifically the need to explicitely enable them) is one of the several “papercuts” you get when you start using it. This reminded me of Josef Sipek’s “Modern Mercurial” blog series which starts with an article precisely about that problem:

Then it suddenly hit me —- before these tweaks, I had been using Mercurial like it’s still 2005!

I think this is a very important observation. Mercurial didn’t seem to be improving because none of the user-visible changes were forced onto the users.

The problem is that the Mercurial devs have an extremely strict approach to how the CLI should behave, and how no breaking changes should ever be introduced. This means that:

  1. No “dangerous” commands should be accessible by default (“_don’t give the user opportunities to shoot their own foot_”), which explains why history rewriting commands like rebase are disabled out-of-the-box.
  2. Things that were later added (like colours, pager support, etc.) were often done in an optional extension to not break previous behaviour.

Arguably, these strict rules are partially the reason why the Mercurial CLI is so nice to use compared to other CLIs like Git’s, but they’re also obviously causing a lot of pain elsewhere.

I naively think this might be somewhat fixable by:

  • Making the first hg run setup some sane default if it doesn’t find any user .hgrc (i.e. better bootstrapping).
  • Relaxing some of the strict CLI rules by realizing that most use-cases that rely on specific historical behaviours (like automated scripts) are already most probably setting environment variables like HGPLAIN, in which case Mercurial can disable some of the more “human facing” features.

But of course, it’s lot more complicated than this… and to some degree, this was addressed with the tweakdefaults setting (formerly known as “friendly hg”), but, ironically enough, you still need to know about enabling it, since it default to false, of course.

Staging areas

The fourth post talks about how Mercurial doesn’t have a staging area (a.k.a. index) like in Git.

It’s kind of funny to me that we have people who started with Git as their first (and sometimes only) VCS, and it will soon dawn on them that, frankly, there’s nothing out there quite like Git’s index (well, at least not in any of the half-dozen VCSes I’ve used so far). Git’s pretty unique on that front.

Although I don’t recommend trying to emulate a tool’s idiosyncratic workflow when using another tool, people coming from Git invariably ask about this so there’s always been some partial answer for Mercurial. A few years ago, the MQ extension was that answer (it kinda gives you something that looks like multiple staging areas!), but it seems that most of the Mercurial community has moved away from it (I have too). MQ is still available for those who want it, but these days it seems that using secret phases and history rewriting is more common (and it also kinda gives you multiple staging areas too!).

I don’t really do that, but I imagine it would work along the lines of:

[alias]
newstage = commit -s -m "STAGING AREA"
upstage = commit --amend

So when you start working on something new, you push your work-in-progress with hg newstage into a secret commit called “STAGING AREA”. Since it’s secret, it won’t get pushed and will stay local. Then, as you keep working, you run hg upstage every now and then to “grow” that commit. When it’s ready, you change that commit’s phase to draft. It’s a bit clunky (there are 2 aliases when ideally there would be only one) but you get the idea, and with a bit of scripting I’m sure that it’s possible to get it down to a similar UX as Git’s.

Twelve days to go

Anyway, we’re still half-way to Christmas so check out Kamal’s blog for the rest of the series (assuming he keeps it going :) ).


Modern Mercurial

I recently came across Josef Sipek’s series of articles on setting up a “modern Mercurial”. In the first post, he realizes that he was missing out on a lot of the new features that had been added to our beloved hg along the years, due to the maintainers' policy of not changing the default CLI behaviour.

I realized I had the opposite problem – my .hgrc is a loose collection of snippets I gathered from all around the web, at various times, and as such it has accumulated several layers of Mercurial history.

Extensions

The main thing to clean up was my list of extensions. I had 14 built-in extensions enabled, several of which had been deprecated in favour of something better, or incorporated in the core. Now I’m down to 8:

  • color: self-explanatory… make it pretty.

  • extdiff: lets you specify an external diff/merge tool.

  • histedit: lets you shoot yourself in the foot, a.k.a editing history with a workflow similar to git rebase --interactive.

  • pager: lets you specify a custom “pager”, i.e. the thing that stops the text from scrolling off the top of the screen, and lets you “paginate” a command’s long output, like hg log. This mostly saves you from always having to do hg whatever | less or similar.

  • purge: adds a command for removing all untracked files. Useful sometimes to clean up temp files, .orig files, etc.

  • rebase: this is a basic operation for DVCSes so go figure why this isn’t enabled by default, especially now that we have phases.

  • schemes: super useful for making aliases of hosting providers like Github, Bitbucket, and even your own private domains.

  • shelve: I used to use that, along with MQ, to manage my works-in-progress, but now that I’m using evolve (see below), I don’t really use it anymore… still, I prefer to keep it around.

I also have a few third-party extensions:

  • hg-git: required for mirroring Mercurial repositories to Github.

  • hg-onsub: run a command on all sub-repositories. I don’t use sub-repositories much anymore, since I figured they are a pain to work with, but it’s still occasionally handy to batch-pull/update sub-repos.

  • hg-allpaths: run hg pushall and push to all paths in one go.

  • evolve: enables the changeset evolution features that are inactive by default in the Mercurial core. This is totally awesome, and quite mind-blowing sometimes.

  • terse-status: when you have a directory with lots of untracked files and nothing else, make hg status show you just the directory… not 3 pages of untracked filenames.

Logging

Nothing fancy here, really… I’ve cloned Steve Losh’s templates a long time ago and never looked back.

Multi-plaform

One cool thing that .hgrc files have is support for including other config files that may or may not exist, and support for environment variable expansion.

My .hgrc is actually generated by my Dotfilesinstall script, but it includes the “real” hgrc (which you can see here). At the end, I can include further configuration files, like a “local” file that could contain secret or temporary stuff, and a platform specific configuration file:

# OS-specific settings
%include hgrc-${OS}

# Local settings (if any)
%include hgrc-local

That’s how I keep things working between Mac, Linux, and Windows between home and work.


Mercurial's onsub and mixed sub-repos

If you’re using Mercurial with mixed sub-repositories (i.e. sub-repositories handled by different revision control systems), you may be interested in this: I just got a patch accepted into the onsub extension.

The extension lets you run commands on your sub-repositories. For example, with my own dotfiles repository, running on Windows:

> hg onsub "echo I'm in %HG_SUBPATH%"
I'm in lib\hg\hg-git
I'm in lib\hg\onsub
I'm in vim\bundle\badwolf
I'm in vim/bundle/colorschemes
I'm in vim/bundle/commentary
I'm in vim/bundle/ctrlp
I'm in vim/bundle/easymotion
I'm in vim/bundle/fugitive
I'm in vim\bundle\gundo
I'm in vim/bundle/haml
I'm in vim\bundle\lawrencium
I'm in vim/bundle/markdown
I'm in vim/bundle/nerdtree
I'm in vim\bundle\piecrust
I'm in vim/bundle/powerline
I'm in vim/bundle/ragtag
I'm in vim/bundle/repeat
I'm in vim/bundle/solarized
I'm in vim/bundle/supertab
I'm in vim/bundle/surround
I'm in vim/bundle/syntastic
I'm in vim/bundle/vimroom

As you can see, I’ve got quite a few sub-repos. However, some are Mercurial sub-repos, while others are Git sub-repos (that’s one of the nice features of Mercurial: it has decent interop with other RCSes). Which ones are which, though? That’s easy, there’s a new HG_SUBTYPE environment variable now:

> hg onsub "echo I'm in [%HG_SUBTYPE%]%HG_SUBPATH%"
I'm in [hg]lib\hg\hg-git
I'm in [hg]lib\hg\onsub
I'm in [hg]vim\bundle\badwolf
I'm in [git]vim/bundle/colorschemes
I'm in [git]vim/bundle/commentary
I'm in [git]vim/bundle/ctrlp
I'm in [git]vim/bundle/easymotion
I'm in [git]vim/bundle/fugitive
I'm in [hg]vim\bundle\gundo
I'm in [git]vim/bundle/haml
I'm in [hg]vim\bundle\lawrencium
I'm in [git]vim/bundle/markdown
I'm in [git]vim/bundle/nerdtree
I'm in [hg]vim\bundle\piecrust
I'm in [git]vim/bundle/powerline
I'm in [git]vim/bundle/ragtag
I'm in [git]vim/bundle/repeat
I'm in [git]vim/bundle/solarized
I'm in [git]vim/bundle/supertab
I'm in [git]vim/bundle/surround
I'm in [git]vim/bundle/syntastic
I'm in [git]vim/bundle/vimroom

That makes it possible to do something slightly different depending on the sub-repo type, but it’s still tedious. For example, the most common operation for me is to pull and update all those sub-repos. The commands are different (hg pull -u vs. git pull) and doing an if statement in Bash or Cmd is cumbersome, especially as a one-liner argument.

That’s where the other new feature comes in: there’s a new -t/--type option that filters sub-repos based on their type:

> hg onsub -t hg "echo Mercurial subrepo: %HG_SUBPATH%"
Mercurial subrepo: lib\hg\hg-git
Mercurial subrepo: lib\hg\onsub
Mercurial subrepo: vim\bundle\badwolf
Mercurial subrepo: vim\bundle\gundo
Mercurial subrepo: vim\bundle\lawrencium
Mercurial subrepo: vim\bundle\piecrust

This makes it easy to bring all the sub-repos up to date:

> hg onsub -t hg "hg pull -u"
> hg onsub -t git "git pull"

Hopefully it makes life easier for a few other people out there… it sure does for me!


Using Mercurial to publish a PieCrust website

These days, all the cool hipster kids want to deploy stuff by pushing a Git or Mercurial repository up to their server.

hipster cat

And that’s pretty cool indeed, because you basically update your website by doing something like:

hg push myserver

So here’s how you can do it with PieCrust (although 90% of this article has nothing to do with PieCrust):

  1. Installing Git/Mercurial/whatever on your server
  2. Setting up your SSH keys
  3. Pushing your repository
  4. Defining hooks/triggers

Keep reading for the meaty details…

Read more...