E-Scribe : a programmer’s blog

About Me

PBX I'm Paul Bissex. I build web applications using open source software, especially Django. Started my career doing graphic design for newspapers and magazines in the '90s. Then wrote tech commentary and reviews for Wired, Salon, Chicago Tribune, and others you never heard of. Then I built operations software at a photography school. Then I helped big media serve 40 million pages a day. Then I worked on a translation services API doing millions of dollars of business. Now I'm building the core platform of a global startup accelerator. Feel free to email me.

Book

I co-wrote "Python Web Development with Django". It was the first book to cover the long-awaited Django 1.0. Published by Addison-Wesley and still in print!

Colophon

Built using Django, served with gunicorn and nginx. The database is SQLite. Hosted on a FreeBSD VPS at Johncompanies.com. Comment-spam protection by Akismet.

Pile o'Tags

Stuff I Use

bitbucket, Django, Emacs, FreeBSD, Git, jQuery, LaunchBar, Markdown, Mercurial, OS X, Python, Review Board, S3, SQLite, Sublime Text, Ubuntu Linux

Spam Report

At least 236509 pieces of comment spam killed since 2008, mostly via Akismet.

Branching and merging in real life

At work I still mostly use Subversion for version control. Its main selling points: stable, performs as expected, integrates nicely with Trac, holds all our old stuff (legacy inertia).

Note that "pain-free branching and merging" is not on that list. (And don't give me the old "branching is cheap in svn!" line. It's not about the branching, it's about the merging.) A couple years ago I started also using Mercurial and plan to eventually replace svn with it entirely. The aspect of Mercurial that made my life better recently is its support for branching and merging.

The scenario: an important internal web app (in use all day every school day) needed some significant changes on a short timetable. Normally I'd work on the app thus: edit the staging copy, commit, update the live copy. I didn't want to take that approach here. I knew that during the development window there might arise unrelated urgent change requests; I wanted to keep the new code isolated during development, but also deploy and track those unrelated urgent changes. Branching seemed like the right approach.

I could have made a full clone of the app (hg clone mainrepo newrepo). However, handling environment dependencies (web server, PythonPath, database) would have added time and fussiness to the job, and time was in short supply. So, using Mercurial's named-branches feature, I made a new branch (hg branch newstuff) right inside the fully-functional staging copy of the app. That way I was able to develop and test as usual, secure that my unproven work-in-progress was not "polluting" the current app's revision history.

To handle "unrelated urgent changes" as mentioned above, I'd:

  1. Commit any current work on the "newstuff" branch
  2. Switch to the main branch (hg update -r default)
  3. Make the urgent change, test, commit, update the live copy
  4. Switch back to the new branch (hg update -r newstuff)

It took me a couple tries to understand how branch-switching worked, but it's simple: you really are updating your working directory to a new revision, it just happens to be a revision stored in a different branch from the current one.

It was fun looking at the graph (via HgWeb) and seeing my two parallel branches with their individual commits.

The moment of truth came at the end of the day Friday, when it was time to merge the tested and complete "newstuff" code with the current live codebase. It was dead simple, and effectively instantaneous. Condensed version: hg update -r default; hg merge -r newstuff; hg ci -m "merged new stuff". Followed by: update live copy and let out a big sigh.

Saturday, November 7th, 2009
+ +
8 comments

Comment from Joe , later that day

You haven't made it terribly clear, but I guess you were making the significant changes on the staging server as it already had the infrastructure ready. Was why it was important to be able to switch between branches and make changes on the original branch?

Is this correct?

Comment from Paul , later that day

Sorry for the confusion. The challenge in writing a post like this is giving enough detail about the working setup to make the story clear, but not descending into uninteresting details. Anyway, your suppositions are correct.

Comment from Chris , later that day

How would one bring forward the changes in default into newstuff branch to test before merging into default?

Comment from codekoala , 3 days later

It's neat stuff huh! I was very wary of branching/merging when I used SVN, but I find it to be very easy and reliable with Mercurial. Mercurial FTW!

Comment from Paul , 4 days later

Chris -- for my purposes "bring forward the changes" and "merge" mean the same thing. So, the command sequence in the last paragraph of my post is the answer to your question as I understand it. After I've tested the merged code on the staging side, I update the live side by doing an hg fetch from staging.

Comment from Chris , 5 days later

Paul, I was thinking more along the lines of: working on a new feature newstuff but want to bring in the bugfixes being made in default. I'm not done with newstuff yet, I just want to make sure it tests against the default bugfixes.

If I'm reading right your last paragraph is merging into default, whereas I wasn't to merge into newstuff from default. Do I just need to reverse the commands in the last paragraph?

Comment from Paul , 5 weeks later

Chris: Sorry for the delay in responding, but: yes. Swapping "default" and "newstuff" in the last paragraph's example will do exactly what you want.

(Just had occasion to do that very thing a few minutes ago, in fact, which reminded me to come here and reply to you!)

Comment from Paul , 7 months later

Just wanted to follow up to note that, many months later, this workflow continues to please. At times I've had three separate branches underway, but never any confusion. Subversion is only a legacy system for me now and I look forward to leaving it behind.

Comments are closed for this post. But I welcome questions/comments via email or Twitter.