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:
- Write the commit message.
- Write the code.
- 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):
function aim() { vim ./COMMIT_MSG; }
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:
COMMIT_MSG
Usage
- 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 nameCOMMIT_MSG
.
To read or modify the commit message typeaim
again. - Write the code as you'd normally do and add/stage the files you'd like to commit.
- 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 theCOMMIT_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
- Clone the repository:
git clone git@github.com:alpipego/git-cdd.git
- Change into the directory and run the installer:
cd git-cdd && sudo make install
Usage
- Type
git cdd aim -m 'Message'
in the Terminal.
The command creates a new (temporary) file in the current repository with the nameCDD_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.
- Write the code as you'd normally do and add/stage the files you'd like to commit.
- 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 theCDD_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...