#!/bin/bash # This script checks if a commit message follows the specified format. # It's designed to be used as a 'commit-msg' git hook. # Format: # : # # [optional] # # [ref/close]: # --- Configuration --- # An array of allowed commit types ALLOWED_TYPES=(feat fix refactor perf style test docs build chore revert) # --- Colors for Output --- RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # The first argument to the hook is the path to the file containing the commit message COMMIT_MSG_FILE=$1 # --- Validation Functions --- # Function to print an error message and exit # Usage: error_exit "Your error message here" error_exit() { # >&2 redirects echo to stderr echo -e "${RED}ERROR: $1${NC}" >&2 echo -e "${YELLOW}Commit message format is incorrect. Aborting commit.${NC}" >&2 exit 1 } # --- Main Logic --- # 1. Read the header (first line) of the commit message HEADER=$(head -n 1 "$COMMIT_MSG_FILE") # 2. Validate the header format: : # Regex breakdown: # ^(type1|type2|...) - Starts with one of the allowed types # : - Followed by a literal colon # \s - Followed by a single space # .+ - Followed by one or more characters for the description # $ - End of the line TYPES_REGEX=$( IFS="|" echo "${ALLOWED_TYPES[*]}" ) HEADER_REGEX="^($TYPES_REGEX): .+$" if ! [[ "$HEADER" =~ $HEADER_REGEX ]]; then error_exit "Invalid header format.\n\nHeader must be in the format: : \nAllowed types: ${ALLOWED_TYPES[*]}\nExample: feat: add new user authentication feature" fi # 3. Validate the footer (last line) of the commit message FOOTER=$(tail -n 1 "$COMMIT_MSG_FILE") # Regex breakdown: # ^(ref|close) - Starts with 'ref' or 'close' # : - Followed by a literal colon # \s - Followed by a single space # N25B- - Followed by the literal string 'N25B-' # [0-9]+ - Followed by one or more digits # $ - End of the line FOOTER_REGEX="^(ref|close): N25B-[0-9]+$" if ! [[ "$FOOTER" =~ $FOOTER_REGEX ]]; then error_exit "Invalid footer format.\n\nFooter must be in the format: [ref/close]: \nExample: ref: N25B-123" fi # 4. If the message has more than 2 lines, validate the separator # A blank line must exist between the header and the body. LINE_COUNT=$(wc -l <"$COMMIT_MSG_FILE" | xargs) # xargs trims whitespace # We only care if there is a body. Header + Footer = 2 lines. # Header + Blank Line + Body... + Footer > 2 lines. if [ "$LINE_COUNT" -gt 2 ]; then # Get the second line SECOND_LINE=$(sed -n '2p' "$COMMIT_MSG_FILE") # Check if the second line is NOT empty. If it's not, it's an error. if [ -n "$SECOND_LINE" ]; then error_exit "Missing blank line between header and body.\n\nThe second line of your commit message must be empty if a body is present." fi fi # If all checks pass, exit with success echo -e "${GREEN}Commit message is valid.${NC}" exit 0