~ / initial commit / Ruby on Rails

Issue #08 — "Initial"

Ruby on Rails

The first commit of Rails is 296 files, 30,881 lines, and a one-word message: 'Initial'. It's the bundling of a framework that already existed inside Basecamp.

frameworkruby
the commit
repo  rails/rails
sha  db045dbbf6
author  David Heinemeier Hansson
date  2004-11-24
message  "Initial"
stats  296 files · +30,881 lines

Every issue of this newsletter so far has been about a project that is recognizably "young" in its first commit. Rails is different. Rails was already a finished product with a user base on day one; it just happened to be one that had been living inside an application, not beside it.

One word. No punctuation. A 23-year-old Danish developer in Chicago named David Heinemeier Hansson, who was building a project management app for a company called 37signals, hit enter on a 296-file commit and called it "Initial."

The project management app was Basecamp. The framework he extracted from it, that he is extracting, right here, in this commit, is Ruby on Rails.

1. Extraction as a design philosophy

DHH has spent a large part of his public career arguing for one very specific idea about how good software gets made: extract, do not invent. Do not sit down to build a framework. Build a real product that solves a real problem. When you notice you are repeating yourself, pull the repeated parts out into libraries. Ship those libraries. That is how you get a framework that is actually useful, because every part of it was forged by the pressure of shipping a real thing.

Rails is the most famous example of this philosophy, and this commit is the physical evidence that he meant it. Rails did not start life as a framework. It started as the reusable parts of Basecamp, after Basecamp had been in production and making money. The first commit is what those parts looked like when they were ready to stand on their own.

You can see the extraction in the directory structure. The top level of the repo is not lib/ or src/. It is a set of subprojects:

actionmailer/
actionpack/
activerecord/
activesupport/
railties/

Each of these was already a separate gem by the time of this commit: actionpack for controllers and views, activerecord for the database layer, actionmailer for sending email, activesupport for the Ruby utilities that the others share, railties for the glue that makes them behave as a single thing. Rails, the brand, is the merger of five libraries that had been living in five different places and shipped together for the first time here.

This is a very different kind of "initial commit" from most. It is the bundling of a project that already existed in pieces. They already had users. The first commit is when they moved into one house.

2. What's inside the house

296 files. 30,881 lines of Ruby. Five subprojects, each with its own Rakefile, CHANGELOG, MIT-LICENSE, README, and install.rb. This was before the Ruby community had settled on a single standard for packaging and distribution. Bundler did not exist, gem was new, Rubygems.org would not exist for another five years. So each subproject came with its own hand-rolled install script.

A few details worth singling out:

  • actionmailer/lib/action_mailer/vendor/tmail/: a vendored copy of TMail, the Ruby email parsing library, committed directly into Rails. In 2004, "vendoring" meant copying someone else's source code into your repo. There was no package manager to do it for you. Half the actionmailer line count is TMail.
  • actionmailer/lib/action_mailer/vendor/text/format.rb: 1,447 lines. The longest file in the initial commit of Rails is a third-party text-formatting utility that was vendored in to support plain-text email templates. Rails shipped with more vendored code than original code in places.
  • No tests in some subprojects, extensive tests in others. The extraction was uneven. Some of the code was battle-tested against Basecamp's production traffic. Some of it was newer: the framework parts that had been written during the extraction, as DHH generalized away from Basecamp's specifics.
  • railties/: the weirdly-named subproject that everyone who learns Rails wonders about. "Railties" is the glue between the other subprojects: command-line generators, initializers, the mechanism that boots an application. The name is a pun on "railroad ties" (the wooden crossbeams under train tracks), which is the kind of pun that was beloved in 2004 and aged into a permanent fixture of the Rails source tree.

If you had never seen Rails before and you read this commit cold, the thing that would stand out is how complete it feels. All the core abstractions were already in place. Routing, view templates, ActiveRecord associations, migrations, mailer support. There was already a generate scaffold command. The project had not even started yet on GitHub (GitHub was three years from existing) and it was already recognizable as the framework that would define Ruby for the next fifteen years.

This is the ultimate payoff of the "extract, don't invent" approach. When your framework is the distilled leftovers of a real application, your day-one API is already validated, because it was designed by the need to build something. DHH didn't design Rails by imagining what a web framework ought to look like. He designed Basecamp, and then he took the parts he could reuse, and those parts were Rails.

3. The one-word commit message

"Initial."

It is possible to read too much into commit messages, and I may be about to do that, but I think the one-word message here fits the gesture. There is no "Initial commit of Rails 1.0 alpha, containing ActionPack, ActiveRecord, and friends, extracted from Basecamp". No salesmanship, no explanation. Just "Initial," as if to say: this is the new starting line. Everything before this was prologue.

DHH is not a man who generally undersells his own projects. If he had wanted to make a speech in the first commit, he would have. The restraint feels deliberate. The work is the statement.

4. Aftermath

Rails 1.0 would ship thirteen months after this commit, on December 13, 2005. Within three years, it would be the most talked-about web framework in the world, and "Rails-like" would become a common compliment applied to frameworks in every other language. Django, Laravel, Phoenix, Play, Ember, and dozens of others would borrow from Rails' conventions: URL routing shapes, MVC layouts, the idea of convention over configuration, generators, migrations.

Most of the ideas were not new. Rails' gift was coherence: shoving them all into one framework in a way that felt inevitable once you had used it. The first commit is the moment that coherence became a public artifact.

And it is called "Initial." Four extra characters, and DHH didn't feel like typing them.

5. Footnotes from the commit log

  • The repository was originally on Subversion, then migrated to git, and the 2004 date was preserved during the migration. The actual git repo at github.com/rails/rails was created in 2008.
  • "DHH" typed this commit on a machine in Copenhagen or Chicago (he was splitting time between the two at the time), using a Ruby installation that predated Ruby 1.9. Most of Rails 1.0 ran on Ruby 1.8.
  • 37signals, the company that was paying him to build Basecamp, is now called Basecamp LLC, and is also the company that built HEY and Once. DHH has never worked anywhere else.
  • The other famous "extraction" in DHH's career is the web server Unicorn, which came out of GitHub, not 37signals. He is rightfully unapologetic that extraction is the only good way to write libraries.