#!/bin/bash # ABOUTME: Commit-msg hook that validates commit messages follow conventional commit format. # ABOUTME: Install with `make install-hooks`. set -e COMMIT_MSG_FILE="$1" COMMIT_MSG=$(cat "$COMMIT_MSG_FILE") # Pattern for conventional commits: type(scope)?: message # Types: feat, fix, chore, docs, style, refactor, perf, test, build, ci PATTERN='^(feat|fix|chore|docs|style|refactor|perf|test|build|ci)(\([[:alnum:]_-]+\))?!?:.+$' # Get the first line (subject) of the commit message FIRST_LINE=$(echo "$COMMIT_MSG" | head -n 1) # Skip validation for merge commits if echo "$FIRST_LINE" | grep -qE '^Merge '; then exit 0 fi # Skip validation for revert commits if echo "$FIRST_LINE" | grep -qE '^Revert '; then exit 0 fi if ! echo "$FIRST_LINE" | grep -qE "$PATTERN"; then echo "Error: Invalid commit message format." echo "" echo "Commit message: '$FIRST_LINE'" echo "" echo "Expected format: ()?: " echo "" echo "Valid types:" echo " feat - A new feature" echo " fix - A bug fix" echo " chore - Maintenance tasks" echo " docs - Documentation changes" echo " style - Code style changes (formatting, etc.)" echo " refactor - Code refactoring" echo " perf - Performance improvements" echo " test - Adding or updating tests" echo " build - Build system changes" echo " ci - CI configuration changes" echo "" echo "Examples:" echo " feat: add user authentication" echo " fix(auth): resolve token expiration issue" echo " chore(deps): update dependencies" echo " feat!: breaking change in API" exit 1 fi echo "Commit message format valid."