Policing commit messages to conform to a semver-like standard
Tags: git
Published: 2023-06-01 05:01:41

---
title: Policing commit messages to conform to a semver-like standard
author: ''
published: true
publishDate: Thu Jun 01 2023
displayDate: 1 Jun
cover: 'https://i.ibb.co/swkd4P2/ccc.jpg'
cover_image: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e3/Sarajevo_City_Panorama.JPG/2560px-Sarajevo_City_Panorama.JPG'
description: Policing commit messages to conform to a semver-like standard
tags:
  - git
id: 1487900
date: '2023-06-01T05:01:41Z'
---

## Policing commit messages to conform to a semver-like standard

I've been using a git hook to police commit messages for a while now to ensure that they conform to a semver-like standard. As someone thats prone to writing commit messages like "fixing stuff" or "more stuff" this has been a great way to enforce better commit messages. Lets look at the hook below.

```bash
# ~/.config/git/hooks/commit-msg

#!/usr/bin/env zsh
declare -r msg=$(< $1);
title=${msg%%$'\n'*}
[[ ${#title} -lt 20 ]] && echo 'Please enter a more informative commit message' && exit 1
[[ ${#title} -gt 50 ]] && echo 'Please keep commit summary below 51 characters' && exit 1
[[ $msg == wip:[[:space:]]* ]] && exit 0
[[ $msg == fix:[[:space:]]* ]] && exit 0
[[ $msg == feat:[[:space:]]* ]] && exit 0
[[ $msg == feat!:[[:space:]]* ]] && exit 0
[[ $msg == docs:[[:space:]]* ]] && exit 0
echo "your commit should begin with fix:, feat:, feat!:, docs:, or wip:"
echo "dont forget the colon, and the space after it"
echo "commits prefixed with wip must be squashed before submitting PR"
exit 1
```

This hook is written in zsh, but it should be easy to convert to bash if thats your preference. The hook is placed in `~/.config/git/hooks/commit-msg` and is made executable with `chmod +x ~/.config/git/hooks/commit-msg`. The hook is run after you write your commit message and save it. If the hook exits with a non-zero exit code, the commit is aborted. The hook checks that the commit message is between 20 and 50 characters, and that it begins with one of the following prefixes: wip:, fix:, feat:, feat!:, or docs:. This only affects the title or first line of the PR, the body can be any length.

**fix:** (0.0.1), **feat:** (0.1.0), and **feat!:** (1.0.0) conform to semver standards, and can be used with a github action like conventional-changelog-action to auto-update package.json, changelog.md, and create releases on github.

**docs:** signifes a change to documentation, and does not affect the version number.

**wip:** is a special prefix that allows you to commit work in progress. These commits should be squashed before submitting a PR.

Now if we try commiting with a message that doesn't conform to the above standards we get the following error.

```bash
☁  cerico@kelso:data-for-france ➜ (kos-13-adding-data-for-strasbourg) git commit -m "im just fixing stuff"
your commit should begin with fix:, feat:, feat!:, docs:, or wip:
dont forget the colon, and the space after it
commits prefixed with wip must be squashed before submitting PR
```

The above hook prevents commits which don't conform to the semver standard, but sometimes we might want to be able to add temporary "fixing stuff" type commits that aren't intended to make it into the main branch. The hook allows me us do so as long as the messages is prefixed with **wip:**. When its time to submit a PR we can see clearly any commits that should be squashed or otherwise tidied up before submitting the PR. In a later post I'll show another function `ghpr`, which will catch any wip commits before creating the PR, as well as filling in the title and body of the PR.