DEV Community

Shreyas Minocha
Shreyas Minocha

Posted on • Updated on

My commit message workflow

This article was originally published on http://shreyasminocha.me/blog

Commit message example

I totally obsess over commit messages. I often spend minutes staring into space trying to come up with the best way to summarize the changes a commit brings. I religiously follow the seven rules of good commit messages. As you might have guessed, I've spent some time developing a workflow for writing commit messages.

I use Sublime Text 3 for most of my text-editing needs. I've also set it as my core editor.

git config --global core.editor "subl -n -w"
Enter fullscreen mode Exit fullscreen mode

Note: The above requires the you to install the subl command if it doesn't work out of the box. Installation instructions: macOS · Linux · Windows.

Earlier, I used to use a package to provide syntax highlighting for commit messsages. However, build 3170 has brought native support for various git formats, commit message included.

Sublime allows you to override settings for specific syntaxes. You can edit these from ‹Preferences› → ‹Settings – Syntax Specific›. Here's my Git Commit.sublime-settings file:

{
    "rulers": [50, 72],
    "spell_check": true,
    "word_wrap": "true",
    "wrap_width": 72,
    "font_size": 14,
    "draw_centered": true
}
Enter fullscreen mode Exit fullscreen mode

Note: VS Code fans can do it this way.

Somewhere on the internet, I found a template for commit messages:

# If applied, this commit will…


# Explain why this change is being made

# Provide links to any relevant tickets, articles or other resources
Enter fullscreen mode Exit fullscreen mode

This template makes it easier to frame commits in accordance with the seven rules I mentioned earlier. I can't seem to remember where I found this, but in my attempts to trace it, I found a blog post providing a very similar template. As it turns out, git allows you to use a text file as a template for your commit messages.

git config --global commit.template "/Users/example/dotfiles/commit-msg-template"
Enter fullscreen mode Exit fullscreen mode

When I started using this template, I had a small pet peeve about my setup. Running git commit would fire up Sublime with the cursor on the first line and to actually write the message, I would have to move the cursor one line below. With research and some experimentation, I solved the issue:

git config --global core.editor = "sublime -n -w $1:2"
Enter fullscreen mode Exit fullscreen mode

The $1:2 at the end of the value opens the argument with the cursor on row 2.

Another one of my pet-peeves with the commit message text is this little snippet above the commented out git status:

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
Enter fullscreen mode Exit fullscreen mode

While helpful to the newbie, this little notice ended up becoming an annoyance. I found a helpful answer on StackOverflow which advised using a global prepare-commit-msg hook. If you don't already have a global git hooks directory, create one and tell git about it:

git config --global core.hookspath "/Users/example/dotfiles/git-hooks"
Enter fullscreen mode Exit fullscreen mode

Create prepare-commit-msg in said directory with the following content:

#!/usr/bin/env bash

sed -i.bak '/^# Please/,/^#$/ d' $1 && rm $1.bak
Enter fullscreen mode Exit fullscreen mode

Edit: This snippet originally used perl followed by grep. Thanks @shaiay and @jwmevans_77 's for your suggestions in the comments.

Make sure the hook is set to be executable with chmod +x. Now that pesky help notice will bother you no more.

Relevant xkcd

Recently, I found this really cool utility which allows you to validate commit messages from the command line. I use a modified form of the utility in a global commit-msg hook to automatically validate every commit I make. Create commit-msg in your global git hooks directory:

#!/usr/bin/env bash

commit-msg file $1
Enter fullscreen mode Exit fullscreen mode

Note: The above requires the commit-msg command to be on your $PATH. Install it using npm i -g commit-msg manually from source code.

Again, make sure the script is set to be executable. The result of this hook is that the commit would abort if my commit message does not meet the criteria.

An example of an invalid commit message

Thanks for reading!

Further reading

Top comments (33)

Collapse
 
shaiay profile image
shaiay

You could probably use grep -v instead of perl in your prepare-commit-msg hook

Collapse
 
shreyasminocha profile image
Shreyas Minocha • Edited

I tried this out and it almost worked except grep doesn't allow you to edit a file in-place. So I tried grep -Ev "(# Please.*|# with.*|^#$)" $1 > $1 but that didn't work.

Eventually, the following worked:

grep -Ev "(# Please.*|# with.*|^#$)" $1 > /tmp/msg
cat /tmp/msg > $1

Any better way to do this with grep -v?

Collapse
 
shaiay profile image
shaiay • Edited

According to SO this is really a limitation of UNIX. The best answer I found there is (stackoverflow.com/a/29735702/5863381)

but really your solution is just fine. You can add some error checking (and make it into a one-liner):
grep -Ev .... %1 > /tmp/msg && cat /tmp/msg > $1
(this way the cat will only execute if the grep didn't produce an error)

Thread Thread
 
jwmevans_77 profile image
James Evans • Edited

Why not use sed?
You could do the following:
sed -i '/\(# Please.*\|# with.*\|^#$\)/ d' $1
The -i flag will do the edits in-place, saving you having to create a temp file.
Assuming that the unwanted block always occurs at the same place, you could also do sed -i '/^# Please/,+2 d' $1 (Which will delete the line starting with "# Please" and the next 2 lines as well)

**Just noticed a typo in the second sed statement - There was a missing "/" (fixed now)

Thread Thread
 
shreyasminocha profile image
Shreyas Minocha • Edited

Great idea. I'll update the article to use this.

Edit: I just tried this on macOS and it errors out with sed: 1: ".git/COMMIT_EDITMSG": invalid command code .. With some searching, I learnt that BSD sed (the one that macOS uses) requires an extension with -i. However, even that gives me sed: 1: "/^# Please/,+2 d": expected context address. Apparently the +2 thing is GNU sed specific. The first statement (with -i.bak) didn't error, but didn't remove the lines either. I'm guessing it's because of inconsistencies in implementations of sed.

Thread Thread
 
jwmevans_77 profile image
James Evans • Edited

Does the other sed command work for you (sed -i.bak '/\(# Please.*\|# with.*\|^#$\)/ d' $1)?
You can also try this one: sed -i.bak '/^# Please/,/^#$/ d' $1

To keep things tidy you could make it sed -i.bak '/^# Please/,/^#$/ d' $1 && rm $1.bak

Thread Thread
 
shreyasminocha profile image
Shreyas Minocha

Perfect.

Collapse
 
antogarand profile image
Antony Garand

I usually use the first message from What The Commit, but I get weird looks from my coworkers afterwards.

Collapse
 
shreyasminocha profile image
Shreyas Minocha • Edited

That website is my new source of entertainment.

Collapse
 
rhymes profile image
rhymes

omg mine too. Thanks @antogarand !

Collapse
 
adrianskar profile image
Adrian Skar • Edited

Great! In case someone else needs it;
For the cursor on the first line thing on VS Code
[core]
editor = \"C:\\[yourPath]\\Code.exe\" -g $1:1 --wait

in .gitconfig seems to do the trick.

-VSCode's CLI opts

Collapse
 
asfaltboy profile image
Pavel Savchenko • Edited

Brilliant stuff! By the way, have you ever tried the GitSavvy plugin? If you did, why did you stop ? If you didn't, please try it out and let me know what you think !

Disclaimer: I occasionally contribute to GitSavvy

Also, I'd like to update your examples to use conventionalcommits.org/

Collapse
 
shreyasminocha profile image
Shreyas Minocha

I'll try Git Savvy out, thanks. Yeah, I've heard of conventional commits, but they aren't for me. Whatever works for you, of course. node-commit-msg can be configured to support those, though.

Collapse
 
jknsware profile image
Jason Ware

For anyone having a hard time setting the core.editor, the command should be


$ git config --global core.editor 'sublime -n -w $1:2'

Collapse
 
shreyasminocha profile image
Shreyas Minocha

Thanks for pointing that out. I've added some links to installation instructions.

Collapse
 
vasconce7os profile image
Vasconcelos 🇧🇷

thanks for share it. I can't understand "pet peeve",sorry

Collapse
 
shreyasminocha profile image
Shreyas Minocha

That is perfectly fine. It's a very specific pet peeve and I obviously don't expect everyone to relate to it. Feel free to interpret parts of the post as a proof of concept—such manipulation is possible.

Collapse
 
4lch4 profile image
Devin W. Leaman

A pet peeve is just something that someone finds extremely annoying, more so than other things that might be an annoyance.

Collapse
 
nagarjun profile image
Nagarjun Palavalli

How would you enforce this practice within a team of developers all committing to the same project? Does Git allow you to globally enforce commit templates for a repository?

Collapse
 
levente profile image
Levente

Just FYI, we work on a product (Commit Policy Plugin for Jira) that does just that. It's a Jira app, so it's hard wired to work in Jira, but allows you to enforce all kind of rules (to many VCS, not just Git).

Collapse
 
shreyasminocha profile image
Shreyas Minocha

Good question. As far as I know, no, it doesn't. If there's a neat way to do this, I'd like to know.

Collapse
 
jlouzado profile image
Joel Louzado • Edited

Please tell me you've used commitizen; I'd love to see what kind of customizations you'd do with it. Especially incorporating git-mojis :D

Collapse
 
shreyasminocha profile image
Shreyas Minocha

I did stumble across it some time back but the type(scope): message format isn't for me. I've been experimenting with git-mojis though 😃

Collapse
 
rhymes profile image
rhymes

I didn't know about the seven rules, thank you!

Collapse
 
tinsoldier6 profile image
Jason Gade

Very good article with some helpful links, thanks!

Collapse
 
thehanna profile image
Brian Hanna

This is great! I've been wanting to implement a structure for commits at my job and this seems like a really great jumping off point. Thanks!

Collapse
 
alextrastero profile image
alextrastero

Great article; I have a iTerm badge with the message "If applied, this commit will..." :)

Collapse
 
jrock2004 profile image
John Costanzo

Can you show a screenshot of your git log to see how this looks?

Collapse
 
shreyasminocha profile image
Shreyas Minocha • Edited

Sure. Here's a git log --oneline from the repo for my school's MUN's website.
Link to screenshot

Collapse
 
jrock2004 profile image
John Costanzo

I was hoping to see how your template was used

Thread Thread
 
shreyasminocha profile image
Shreyas Minocha • Edited

Oh! The template's just comments. All lines beginning with '#' are ignored. Here's an example of how it would be used.

# If applied, this commit will…
Fix the Secretariat page on phones

# Explain why this change is being made

# Provide links to any relevant tickets, articles or other resources
Resolves issue #4

It's meant to be used as a guidance in framing the commit message in accordance with the seven principles I linked to in the article. I'm sorry that it wasn't clear. I've edited the article to make that obvious. Thanks!

Collapse
 
jsm91 profile image
Jesse

Awesome article, thanks for sharing!