Adventures in Engineering

Purposeful first commit

“Initial commit” is so uninspiring yet we’ve all committed it somewhere!

I’ve recently found myself creating a noticeable handful of repositories for various projects and it got me thinking: whats in a first commit? It’s the commit that hangs around like a bad smell for years after you make it. It appears in github in that placeholder .gitignore, or in that tiny file that never gets changed. So why think about it?

To me, a first commit helps define what the project intent is. Why are you committing this code? What do you aim to achieve?

This morning I went exploring – whats in a first commit?

How to find the initial commit.

First things first, there can be multiple first commits (well, when it comes to git anyway). For example if you git checkout --orphan you create a ref with no parents. You can also get multiple parentless trees if you merge together repositories – git’s own repository is a great example of this with 7 odd initial commits.

For the purposes of this little experiment I went looking for the most logical first commit using this handy command:

$ git rev-list --max-parents=0 HEAD --format=medium -v

This gives me enough information to make an educated guess on the first commit. If I want more I can just run git show REF.

What’s in an commit?

Every commit made should be useful and detail both what and why a change is made. A message “added X dependency” isn’t as helpful as “X is used for Y”.

Take Chris Beams’ “How to write a commit message” for example. His 7th point highlights a great example of focusing on “what” and “why” rather than “how” you’ve achieved something. The “how” goes in comments alongside your code.

Better first commits

Given that each commit should describe the change it makes, it logically follows that each first-commit should set the stage for what the repository is all about.

Perhaps the best example of this is Linus’ first commit when building git.

commit e83c5163316f89bfbde7d9ab23ca2e25604af290
Author: Linus Torvalds <torvalds@ppc970.osdl.org>
Date:   Thu Apr 7 15:13:13 2005 -0700

    Initial revision of "git", the information manager from hell

Git has since lived up to its vision… no?

Alas, surprisingly very few projects do this.

Committing in open source

I started to explore language repo’s including PHPrubyGo and node; all conveniently found on github.

PHP has 4 initial commits, the earliest in 1999 when migrating from cvs to svn. The project later migrated to git and retained its SVN commit history.

$ php git:(master) git rev-list --max-parents=0 HEAD --format=medium -v
commit 43509370272898f7a346de7e2f4c8a012d00f621
Author: Bob Weinand <bobwei9@hotmail.com>
Date:   Fri Dec 20 14:27:51 2013 +0100

    Merge branch 'master' of sapi/phpdbg into PHP-5.6
    Including phpdbg.

commit dac2297b1062975f5d9ac417dbea518c5823b8a6
Author: Joe Watkins <joe.watkins@live.co.uk>
Date:   Sat Nov 9 14:34:16 2013 -0800

    Initial commit

commit 528006a3b49fd45d6b2803c7b7843b2e7d6929d6
Author: Dmitry Stogov <dmitry@zend.com>
Date:   Wed Feb 13 16:26:47 2013 +0400

    Open Source Release

commit f70a4db647886f65a3e24249351d2c8abc0cdfb3
Author: SVN Migration <svn@php.net>
Date:   Wed Apr 7 18:10:10 1999 +0000

    Standard project directories initialized by cvs2svn.

“Initial commit” popped up again as the foundations of the phpdbg project which was accepted unanimously into the core PHP project.

Go has an odd first commit with a author & committer date that at first impressions is completely off.

$ go git:(master) git rev-list --max-parents=0 HEAD --format=medium -v
commit 7d7c6a97f815e9279d08cfaea7d5efb5e90695a8
Author: Brian Kernighan <bwk>
Date:   Tue Jul 18 19:05:45 1972 -0500

    hello, world

    R=ken
    DELTA=7  (7 added, 0 deleted, 0 changed)

This is however part of a beautiful nod to Go’s origins in C.

$ go git:(master) git log --reverse --format="%h %aI %s" | head -n5
7d7c6a97f8 1972-07-18T19:05:45-05:00 hello, world
0bb0b61d6a 1974-01-20T01:02:03-04:00 convert to C
0744ac9691 1988-04-01T02:02:04-05:00 convert to Draft-Proposed ANSI C
d82b11e4a4 1988-04-01T02:03:04-05:00 last-minute fix: convert to ANSI C
18c5b488a3 2008-03-02T20:47:34-08:00 Go spec starting point.

Ruby shared a similar origin commit to PHP as it was brought across from cvs to svn (and its remained in svn).

$ ruby git:(trunk) git rev-list --max-parents=0 HEAD --format=medium -v
commit 392296c12de9d7f9be03a8205250ba0844cb9d38
Author: (no author) <(no author)@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
Date:   Fri Jan 16 12:13:05 1998 +0000

    New repository initialized by cvs2svn.

    git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Node, however, was founded on dependencies. The irony of which is not lost on me.

node git:(master) git rev-list --max-parents=0 HEAD --format=medium -v
commit 9d7895c567e8f38abfff35da1b6d6d6a0a06f9aa
Author: Ryan <ry@tinyclouds.org>
Date:   Mon Feb 16 01:02:00 2009 +0100

    add dependencies

$ node git:(9d7895c567) cat .gitmodules

[submodule “deps/oi”]

path = deps/oi url = git://github.com/ry/liboi.git

[submodule “deps/ebb”]

path = deps/ebb url = git://github.com/ry/libebb.git

Swift has a nod to its origins in SVN but it appears we have two missing commits of history given that this commit started from R3

swift git:(master) git rev-list --max-parents=0 HEAD --format=medium
commit 18844bc65229786b96b89a9fc7739c0fc897905e
Author: Chris Lattner <clattner@apple.com>
Date:   Sat Jul 17 23:50:59 2010 +0000

    initial swift test


    Swift SVN r3

“Initial Commit”

Beyond these language examples, almost all tools, frameworks, libraries etc. that I explored had a “initial commit” of some kind. All of which were unhelpful.

At least laravel named itself…

$ laravel git:(master) git rev-list --max-parents=0 HEAD --format=medium
commit a188d62105532fcf2a2839309fb71b862d904612
Author: Taylor Otwell <taylorotwell@gmail.com>
Date:   Wed Jun 8 23:45:08 2011 -0500

    initial commit of laravel!

A first commit however should detail what you intend to achieve by committing code. What a project is (or isn’t) is an important foundation on which any project is based.

Take for example Bootstrap. Prior to being released as an open source project it was known as Twitter Blueprint. There’s a nod to that in one of bootstrap’s initial commits.

$ bootstrap git:(master) git rev-list --max-parents=0 HEAD --format=medium
commit 4bb7653f67b60fcf464d6c30e2ebe1b87d2dbc31
Author: Jacob Thornton <jacobthornton@gmail.com>
Date:   Tue Jan 31 17:35:23 2012 -0800

    move examples into docs...

commit eb81782cdbdc68aaebe4fa561b5fbb73ef866611
Author: Mark Otto <markdotto@gmail.com>
Date:   Wed Apr 27 13:53:51 2011 -0700

    Porting over all Blueprint styles to new Baseline repo

Other frameworks including jquerylaravelvue and jekyll all had more or less useless initial commits. Entertainingly, jekyll did thoughtfully include a README.txt… that was an unmodified template. Some digging into Vue’s initial package.json included the description “Lighter-weight Vue on virtual dom” which I guess is something.

$ jquery git:(master) git rev-list --max-parents=0 HEAD --format=medium
commit 8a4a1edf047f2c272f663866eb7b5fcd644d65b3
Author: John Resig <jeresig@gmail.com>
Date:   Wed Mar 22 03:33:07 2006 +0000

    Inital Import.
$ laravel git:(master) git rev-list --max-parents=0 HEAD --format=medium
commit a188d62105532fcf2a2839309fb71b862d904612
Author: Taylor Otwell <taylorotwell@gmail.com>
Date:   Wed Jun 8 23:45:08 2011 -0500

    initial commit of laravel!
$ vue git:(dev) git rev-list --max-parents=0 HEAD --format=medium
commit a879ec06ef9504db8df2a19aac0d07609fe36131
Author: Evan You <yyx990803@gmail.com>
Date:   Sun Apr 10 22:47:28 2016 -0400

    init
$ jekyll git:(master) git rev-list --max-parents=0 HEAD --format=medium
commit d189e05d236769c1e5594af9db4d6eacb86fc16e
Author: Tom Preston-Werner <tom@mojombo.com>
Date:   Sun Oct 19 19:07:26 2008 -0700

    first commit

A better first commit

An initial commit should stand out as a descriptor of the project. Why are you committing this code? What do you aim to achieve.

To that end I ensure that my initial commits contain almost no changes and almost all message. I may add a very basic .gitignore file or a rudimentary README.md at most.

Take endpointer for example; here’s the first commit I ever made to the project:

$ endpointer git:(master) ✗ git rev-list --max-parents=0 HEAD --format=medium
commit 60daa711ce0e46425c000702fd0d58134454bcbd
Author: Jack <jack@developerjack.com>
Date:   Sun Aug 20 14:39:18 2017 +1000

    Endpointer transforms OpenAPI specifications into endpoint documentation.

$ endpointer git:(master) ✗ git ls-tree --name-only -r 60daa711c
.gitignore

My most recent tool in the endpointer project is mario and has a similarly helpful initial commit (from earlier today).

mario git:(master) git rev-list --max-parents=0 HEAD --format=medium
commit dd5813bba7980d571e68573ba0330819f3b390ce
Author: Jack <jack@developerjack.com>
Date:   Sun Nov 5 11:05:01 2017 +1100

    Mario is yet another package management tool for documentation.
    It works well with endpointer and static site content.

So for your next project or repository, think about what you want to achieve and set the stage for the next big open source project!

developerjack

1 comment