Recently in Programming Category
Microbranches in Mercurial, Part I: The Basics
August 27, 2008 2:35 PM
git’s not a bad versioning system—there’s a lot to recommend it, and it’s leaps and bounds ahead of Subversion—but I’m sick and tired of seeing that the big reason to use git instead of Mercurial is because Mercurial lacks microbranching.
Wrong. Well, if you’re going to be pedantic and demand that your microbranching be accessed through a command called branch? Then sure. But you’re all smarter than that, so how about you give me some space to work here and let’s see if we can find equivalent functionality.
In Mercurial, the equivalent of git’s microbranches are called patch queues. They have a different metaphor than git branches (they’re an operational hybrid of branching and rebasing), and therefore arguably less intuitive, but if you’ve already wrapped your head around git’s index, reflog, and associated baggage, using patch queues should be a walk in the park.
What this technique is not for
Microbanching, both as it exists in git and in Mercurial as described here, is for exactly that: microbranches. Use this technique for short-lived features and thought experiments. For long-lived branches, you should continue to use full, cloned Mercurial repositories. The rich merge tracking and change history makes the mild sacrifice in hard disk space well worth it.
First, you’re going to have to enable the mq extension that ships with Mercurial and change some defaults. Open up ~/.hgrc (C:\Documents and Settings\[You]\Mercurial.ini on Windows) and ensure that you have the following lines:
[extensions]
alias=
mq=
[defaults]
diff = -p -U 8
qdiff = -U 8
qimport = -g
qrefresh = -g
qinit = -c
[alias]
qaccept = qdelete -r
[diff]
git=1
Behind the scenes, patch queues are going to be managing a series of patches, just like git does. For that reason, these options switch Mercurial’s diff format to be the same as git’s, adding a lot of extra metadata that will help with rebasing branches later on.
Next, in each repository you want to use this technique in, you’ll need to run hg qinit. This ensures that your repository has patch queues enabled.
Now, let’s say you’re working on a project called GuessMyAge. The program, if you’re curious, looks like this:
#!/usr/bin/env python
# Copyright (c) 2008 Hyperion Intergalactic Shipping Corp. Violators will be shot.
import sys
print "Hi. What do you think my age is?"
age = sys.stdin.readline()
print "Close enough!"
And you decide, I want to make it so that the age is only valid if it’s…a number!, which seems pretty reasonable. Instead of doing your normal hg ci/hg fetch/hg push, let’s do it with a microbranch.
First, let’s start a new patch, and a new patch.
hg qnew ageverify
hg qguard +ageverify
What’s a patch? Unlike in normal Mercurial work, where you make changes and then check them in, when working with mq, you first create a patch with which to associate your change. If you start doing work, then decide what you’re doing should be in a branch, no worries: you can simply run hg qnew -f branchname, and all existing changes will be imported into the new patch.
In order to use patches as microbranches, you also must associate a patch with a guard. The second command above creates a new guard, called ageverify, and associates it with your patch.
Now, you can start making changes. Use all Mercurial commands as usual, except that, instead of using hg ci when you’ve made changes, instead run
hg qrefresh
hg qci -m "Made some changes to GuessMyAge"
Note that the commit log message you enter here is internal to the branch, and will never show up on in the main revision history.
Meanwhile, hg in shows that some changes have been committed on the main line. You need to get back to the main branch and update. Doing that’s easy:
hg qpop -a
hg qselect -n
hg fetch
Cool. So, I want to make my branch be based off this new version. How do I do that? Simple:
hg qselect ageverify
hg qpush -a
hg qrefresh
hg qci -m "Rebased branch off of r123"
Mercurial will perform any necessary merging as normal.
You can have as many “branches” as you want this way. To jump between them, just qpop the one you’re leaving (if any) and qpush the one you want to switch to.
Meanwhile, a couple of days later, you’ve finished adding the age check
#!/usr/bin/env python
# Copyright (c) 2008-2009 Hyperion Intergalactic Shipping Corp. Violators will be killed.
import sys
print "Hi. What do you think my age is?"
age = sys.stdin.readline()
try:
age = int(age)
print "Close enough!"
except:
print "That's not even a number!"
and you’ll probably want to merge it back into the main branch. The entire branch will appear as a single check-in within the repository’s history. To perform the merge, switch to the branch, and then issue:
# Set the commit message for the branch
hg qrefresh -m "Made GuessMyAge only say close enough if you enter a number"
# And then merge it
hg qaccept ageverify
You can then hg push the change out just as if it were any other Mercurial check-in.
Instead decide that your branch sucks and you never want to see it again? Just change out of your branch, and then issue
hg qdelete ageverify
That’s enough to get you started using microbranches for trivial exploratory features or patches. Next, we’ll look at what’s actually going on behind the scenes, and how we can use that knowledge to get something fully as powerful as git branches.
Edit: presearing at reddit noted that the original version of this article contained a series flaw. The flaws were caused because I altered the behavior some of the default mq commands to better match my personal workflow. The examples within this article have been updated to work correctly with a vanilla Mercurial install.
An Overview of Python's Underscore Methods
July 2, 2008 9:51 PM
I’ve never been an especially big fan of Python—faster but less powerful than Ruby, slower and less powerful than Smalltalk and Common Lisp, and not as usefully grungy as Perl—but I’ve become a rather strong pragmatist vis-à-vis programming languages, and realize that Python probably isn’t going anywhere anytime soon, so I’ve been trying to improve my proficiency through activities such as Django Dash (which Tyler and I won) and small coding projects, such as the one-off tasks I have to do at work. It’s a technique that’s served me very well in the past to learn new languages and frameworks.
One of the reasons I’m not a particularly big fan of Python is the pervasive use of underscore methods—methods named __like_this__—to accomplish things that Python’s bondage-friendly design wouldn’t otherwise let you do (e.g., operator overloading, destructors, and functors). To that end, I was happy to discover a concise list of Python’s underscore methods and what they do. If you want a quick overview of what can be accomplished through underscore magic, that page should serve you very well.
Ignoring the firewall
April 15, 2008 6:45 PM
The Coding Monkeys have released Port Map, an application to make accessing computers behind firewalls NATs easier. Unlike Copilot, which tries to work around obstinate routers, Port Map focuses on providing an easy and consistent interface for reconfiguring them. It’s hardly perfect for everything—notably, you have to have permissions to reconfigure the router causing you difficulty, making it unsuitable for corporate environments—but I can see it being quite handy if you’re just trying to ensure you can reach your home computer from work to grab a couple of MP3s.
The Return of Ada
April 15, 2008 2:17 PM
I’m somehow having a really hard time feeling anything but dread about the prospect of a return of Ada. It seems to bear more than a passing resemblance to the last few seconds of Carrie…
Google App Engine now on Amazon EC2
April 14, 2008 5:37 PM
One of my main complaints about Google App Engine is that it locks you into using Google’s servers and APIs, giving you little recourse if Google decides to terminate either the service or your contract. Well, good news: that’s changed—somewhat. Chris Anderson of Grabb.it fame has gotten a proof-of-concept App Engine clone running on Amazon’s EC2 service. Because Anderson has done little more than repackage the App Engine SDK for deployment on EC2, it cannot scale the same way that Google-based hosting (or properly written EC2-hosted apps) can, but it’s a good first step towards decreasing App Engine’s lock-in. If they’re able to layer BigTable on top of SimpleDB or an equivalent system, I could well see App Engine becoming the de facto high-traffic web application architecture.
A Poor Man's Time Machine
April 12, 2008 8:35 PM
One of the cool new features of Mac OS X Leopard is Time Machine, a really simple backup solution for Mac OS X that not only transparently backs up your data, but also does so with an amazingly ugly GUI that lets you quickly jump back to the way that your documents were at any given point in the past. Unfortunately, Time Machine doesn’t run on my Linux boxes, so I’m forced to come up with an alternative.
The good news is that getting a 90% solution is ridiculously easy. On the back-end, all that Time Machine does is create a collection of hard links from one backup set to another. Here’s the bare minimum of a shell script that will back up the last three editions of your home folder to an external drive:
#!/bin/sh
SOURCE=/home/benjamin
DEST=/mnt/tardis
rm -fvr "${DEST}.3"
mv "${DEST}.2" "${DEST}.3"
mv "${DEST}.1" "${DEST}.2"
mv "${DEST}.0" "${DEST}.1"
rsync -av --exclude-from='backup-excludes' --link-dest="${DEST}.1" "${SOURCE}/" "${DEST}.0/"</code>
You’ll obviously need to modify the SOURCE and DEST variables to be something appropriate for your computer. You’ll also need to create a file in your home directory called backup-excludes that’ll look something like this:
Documents/Code/3rd-party
Documents/Code/Builds
.emacs-backups
Add and modify the glob patterns so that it contains a list of things that should be skipped. Now, just make sure your external drive is plugged in, run the script, and presto! Instant backup. Quick and dirty, but gets the job done.
Write Your Own Google Apps
April 8, 2008 11:24 AM
Google has announced Google App Engine, which allows you to write applications that run on Google's infrastructure. I personally would be a bit nervous using the service for anything important—unlike Amazon S3 and EC2, making your own service-compatible alternatives is not feasible, making you inextricably tied to Google—but I suppose it could be useful for certain applications that need high scalability, integration with other Google applications, or both.
Note that all 10,000 initial invitations have already been distributed, but you can sign up to be notified when more become available.
Mercurial v. git
April 7, 2008 4:24 PM
RockStarProgrammer has a great article on the differences between Mercurial and git at a technical level. This is exactly the article I wanted back when I was trying to pick between the various distributed version control systems.
JavaScript for Emacs
April 7, 2008 10:59 AM
Steve Yegge has been working for quite some time on a way to integrate JavaScript with Emacs, allowing you to code extensions in JS rather than elisp. To that end, he recently announced the availability of js2-mode, a new mode for Emacs that brings heavily revamped syntax highlighting, indentation, and on-the-fly parsing for JavaScript code.
I’ve recently been having an internal fight with myself on whether to use vim or Emacs. Although I’ve used Emacs for an incredibly long time, have a massive collection of customization scripts, and know the editor inside and out, I’m being forced to come to the conclusion that vi-based editors may have the upper edge for actually editing text. They’re simply kinder to my hands. Yet every time that I decide to give up vim for good, someone writes a tool like js2-mode that simply cannot be implemented in vim.
Maybe someday vim (or a clone) will become as trivial to modify as Emacs. Until then, I suspect I’m going to have a very hard time letting bad habits die.
Pilots, Programmers, and Perl
April 4, 2008 3:15 PM
I don't normally post chat conversations, but some are simply too good to ignore:
Me: So I'm getting back into Perl. Devin: heh Devin: does your boss know? Me: ? Me: I don't get why I'd need to notify Joel Devin: well, you know Devin: it's like when a pilot starts drinking again Devin: the airline should be notified
I think Devin may have a point.
