Conventional Commits is a standardized way to write commit messages. Following the convention will allow you to achieve a neat commit history that’s easily readable for both humans and machines.
Here’s a quick guide on how to enforce this policy on your local machine so that you are always sure your commits follow the standard.
Create a directory for Git hooks
mkdir -p ~/.git-templates/hooks
Configure Git to use this directory
git config --global core.hooksPath ~/.git-templates/hooks
Create commit-msg
hook
Create file at ~/.git-templates/hooks/commit-msg
:
#!/usr/bin/env bash
commit_msg_file=$1
commit_msg=$(cat "$commit_msg_file")
conventional_regex='^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(!)?(\([a-z0-9-]+\))?: .+$'
if ! [[ $commit_msg =~ $conventional_regex ]]; then
echo "-------------------------------------------------------------------------"
echo " ❌ The commit message does not follow Conventional Commits specification"
echo " (see https://www.conventionalcommits.org/en/v1.0.0):"
echo " Format: type(scope)?(!)?: subject"
echo " Allowed types:"
echo " feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert"
echo " Example: feat(api)!: Add validation to the create-user endpoint"
echo "-------------------------------------------------------------------------"
exit 1
fi
Adjust the error message and the regex as needed.
Examples of valid commit messages
feat: Add new user onboarding flow
fix(api): Correct error-handling for 404 responses
refactor(ui)!: Overhaul navigation for better accessibility
docs: Update README to reflect API changes
Make the hook executable
chmod +x ~/.git-templates/hooks/commit-msg
Existing repos
Existing repos won’t automatically use the new global hooks if they already had .git/hooks
populated. In that case, you can either:
- Remove or rename the repo’s local hooks folder so Git falls back to the global one.
- Or manually copy/symlink the commit-msg hook into each repo’s hooks folder.
Once set, any commit message that fails the regex check will abort the commit with an error message, enforcing Conventional Commits across all your local repos.
If you found this guide useful, consider buying me a coffee ☕️
Top comments (1)
Thanks for posting! Love to see people talking about Conventional Commits!
We use husky to implement a similar commit hook on a per-project basis, and our CI/CD is using semantic-release to directly generate the correct version updates from the conventional commits.
While most of our projects use Conventional Commits, older or acquired projects may not adhere to the same standard. It is a bit inconvenient to manage in multiple repos, but it strikes a balance for us.
Thanks again!