Commit Message Driven Development

In software development, we usually start with writing the code. But what if we'd start by writing out the commit message? Follow me through the concept of commit message driven development.

The common process is writing the code and thinking about the commit message afterward. If you are like me, then the commit message sums up everything you remember working on while skimming through the staged files. This regularly results in commits that aren't logically grouped and everything is just messy enough to not be helpful in the long term. Commit messages like WIP or Bugfixes and minor improvements are known to be the result.

Shoutout to David Hemphill who has turned this antipattern into a disestablishmentarian philosophy. While there might be use cases where this makes sense I strongly believe in the value of helpful commit messages, especially when working in a team or an open-source repository.

Commit Message Driven Workflow

So how exactly would a commit message driven workflow look like? First, we start by writing out the commit message. Second, we write the code. As soon as we're done, we commit the code. This is how the workflow looks like:

  1. Write the commit message.
  2. Write the code.
  3. Commit the code.

By writing the draft of the commit message first, we decide what we're working on. The scope of our task is clear now. With the commit message being written down, we're already in the process and in the mindset to write the code to make it happen. We can modify the commit message later, if necessary.


I came across this idea some time ago. Andrew Feeney published the post Commit Message Driven Development and it completely changed my workflow as a professional developer.

This approach helps me to focus on the actual feature I'm working on. After writing out the commit message I continue to write the code. With the commit message in mind, the scope of the commit is clear.

The concept aligns pretty well with the Ivy Lee productivity method. James Clear, the author of the book Atomic Habits, points out what makes the method so effective:

  • It's simple enough to actually work.
  • It forces you to make a decision.
  • It removes the friction of starting.
  • It requires you to single-task.

For me the last point is the most powerful: it helps me to focus on one thing at a time because doing anything outside of the scope of the commit message is another task/commit.

If you commit to nothing, you'll be distracted by everything. jamesclear.com, The Ivy Lee Method

Benefits

Here are some of the benefits I discovered while working with this approach:

  • Scope
    It helps me to decide what to work on upfront. The commit message defines the scope and holds me accountable. The commit message is like a micro goal.
  • Structure
    It helps me to logically group and later review my commits because each commit has a precise goal.
  • Focus
    It helps me to remember what I decided to work on.
    It also helps me to remember what I was working on in a previous (unfinished or interrupted) session.

Setup

Following up on the post by Andrew Feeney I use these two bash functions to incorporate the concept into my daily routine (jump to update below):

.zshrc
function aim() { vim ./COMMIT_MSG; }
.zshrc
function fire() { vim ./COMMIT_MSG && ( git commit -F ./COMMIT_MSG $* ) && rm ./COMMIT_MSG; }

Additional Setup

In my global .gitignore file I added the following line to not check in the temporary COMMIT_MSG file by accident:

.gitignore
COMMIT_MSG

Usage

  1. Type aim in the Terminal. Write the draft of the commit message in the editor and save the file. This creates a new (temporary) file in the current repository with the name COMMIT_MSG.
    To read or modify the commit message type aim again.
  2. Write the code as you'd normally do and add/stage the files you'd like to commit.
  3. Type fire in the Terminal. This opens the editor with the pre-written commit message again. Update the commit message if necessary and save the file. The function creates a new commit and deletes the COMMIT_MSG file.

The fire function passes through all options. Feel free to append the available commit options provided by Git. For instance, use fire --amend to replace the tip of the current branch by creating a new commit.

Update: Git CDD

Alexander Goller developed a Git plugin for Linux and macOS to make the commit driven workflow even smoother.
Instead of custom bash functions use the available Git CDD plugin:

Installation

  1. Clone the repository:
    git clone git@github.com:alpipego/git-cdd.git
  2. Change into the directory and run the installer:
    cd git-cdd && sudo make install

Usage

  1. Type git cdd aim -m 'Message' in the Terminal.
    The command creates a new (temporary) file in the current repository with the name CDD_COMMIT_MSG that holds the commit message.
  • Type git cdd status to preview the prepared commit message.
  • Type git cdd amend to modify the prepared commit message.
  • Type git cdd forget to delete the prepared commit message.
  1. Write the code as you'd normally do and add/stage the files you'd like to commit.
  2. Type git cdd fire in the Terminal. This opens the editor with the pre-written commit message. Update the message if necessary and save the file. The command creates a new commit and deletes the CDD_COMMIT_MSG file.

What's next?

Give it a try! Start your next task by writing down the goal first and see how it feels. For starters complete the following sentence: If applied, this commit will...