From 020bf55772f8b8a482c62151b39de537d908c841 Mon Sep 17 00:00:00 2001 From: Kasper Date: Sun, 2 Nov 2025 22:02:32 +0100 Subject: [PATCH 1/5] fix: automated commit detection ref: N25B-241 --- .githooks/check-commit-msg.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/.githooks/check-commit-msg.sh b/.githooks/check-commit-msg.sh index 82bd441..f87749a 100755 --- a/.githooks/check-commit-msg.sh +++ b/.githooks/check-commit-msg.sh @@ -23,6 +23,37 @@ 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 +# --- Automated Commit Detection --- + +# Git directory (.git/) +GIT_DIR=$(git rev-parse --git-dir) +# Check for a merge commit +if [ -f "$GIT_DIR/MERGE_HEAD" ]; then + echo "Hook: Detected a merge commit." + # Ensure the message follows a 'Merge branch...' pattern. + first_line=$(head -n1 "$COMMIT_MSG_FILE") + if [[ ! "$first_line" =~ ^Merge.* ]]; then + echo "Error: Merge commit message should start with 'Merge'." >&2 + exit 1 + fi + exit 0 + +# Check for a squash commit (from git merge --squash) +elif [ -f "$GIT_DIR/SQUASH_MSG" ]; then + echo "Hook: Detected a squash commit. Skipping validation." + exit 0 + +# Check for a revert commit +elif [ -f "$GIT_DIR/REVERT_HEAD" ]; then + echo "Hook: Detected a revert commit. Skipping validation." + exit 0 + +# Check for a cherry-pick commit +elif [ -f "$GIT_DIR/CHERRY_PICK_HEAD" ]; then + echo "Hook: Detected a cherry-pick commit. Skipping validation." + exit 0 +fi + # --- Validation Functions --- # Function to print an error message and exit -- 2.49.1 From 0d5e198cad506d495093785d267599b223269a16 Mon Sep 17 00:00:00 2001 From: Kasper Marinus Date: Mon, 3 Nov 2025 14:51:18 +0100 Subject: [PATCH 2/5] fix: pattern matching instead of file existence The previous method of detecting automated commits was error-prone, specifically when using VSCode to commit changes. This new method uses a simple Regex pattern match to see if the commit message matches any known auto-generated commits. ref: N25B-241 --- .githooks/check-commit-msg.sh | 43 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/.githooks/check-commit-msg.sh b/.githooks/check-commit-msg.sh index f87749a..6fbc251 100755 --- a/.githooks/check-commit-msg.sh +++ b/.githooks/check-commit-msg.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script checks if a commit message follows the specified format. # It's designed to be used as a 'commit-msg' git hook. @@ -25,32 +25,31 @@ COMMIT_MSG_FILE=$1 # --- Automated Commit Detection --- -# Git directory (.git/) -GIT_DIR=$(git rev-parse --git-dir) -# Check for a merge commit -if [ -f "$GIT_DIR/MERGE_HEAD" ]; then - echo "Hook: Detected a merge commit." - # Ensure the message follows a 'Merge branch...' pattern. - first_line=$(head -n1 "$COMMIT_MSG_FILE") - if [[ ! "$first_line" =~ ^Merge.* ]]; then - echo "Error: Merge commit message should start with 'Merge'." >&2 - exit 1 - fi - exit 0 +# Read the first line (header) for initial checks +HEADER=$(head -n 1 "$COMMIT_MSG_FILE") -# Check for a squash commit (from git merge --squash) -elif [ -f "$GIT_DIR/SQUASH_MSG" ]; then - echo "Hook: Detected a squash commit. Skipping validation." +# Check for Merge commits (covers 'git merge' and PR merges from GitHub/GitLab) +# Examples: "Merge branch 'main' into ...", "Merge pull request #123 from ..." +MERGE_PATTERN="^Merge (branch|pull request|tag) .*" +if [[ "$HEADER" =~ $MERGE_PATTERN ]]; then + echo -e "${GREEN}Merge commit detected by message content. Skipping validation.${NC}" exit 0 +fi -# Check for a revert commit -elif [ -f "$GIT_DIR/REVERT_HEAD" ]; then - echo "Hook: Detected a revert commit. Skipping validation." +# Check for Revert commits +# Example: "Revert "feat: add new feature"" +REVERT_PATTERN="^Revert \".*\"" +if [[ "$HEADER" =~ $REVERT_PATTERN ]]; then + echo -e "${GREEN}Revert commit detected by message content. Skipping validation.${NC}" exit 0 +fi -# Check for a cherry-pick commit -elif [ -f "$GIT_DIR/CHERRY_PICK_HEAD" ]; then - echo "Hook: Detected a cherry-pick commit. Skipping validation." +# Check for Cherry-pick commits (this pattern appears at the end of the message) +# Example: "(cherry picked from commit deadbeef...)" +# We use grep -q to search the whole file quietly. +CHERRY_PICK_PATTERN="\(cherry picked from commit [a-f0-9]{7,40}\)" +if grep -qE "$CHERRY_PICK_PATTERN" "$COMMIT_MSG_FILE"; then + echo -e "${GREEN}Cherry-pick detected by message content. Skipping validation.${NC}" exit 0 fi -- 2.49.1 From 3c8cee54eb15a9ddd6a795ab3d0cf7beee078820 Mon Sep 17 00:00:00 2001 From: Kasper Marinus Date: Mon, 3 Nov 2025 14:51:18 +0100 Subject: [PATCH 3/5] fix: pattern matching instead of file existence The previous method of detecting automated commits was error-prone, specifically when using VSCode to commit changes. This new method uses a simple Regex pattern match to see if the commit message matches any known auto-generated commits. ref: N25B-241 --- .githooks/check-branch-name.sh | 2 +- .githooks/check-commit-msg.sh | 43 +++++++++++++++++----------------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/.githooks/check-branch-name.sh b/.githooks/check-branch-name.sh index 752e199..0e71c9b 100755 --- a/.githooks/check-branch-name.sh +++ b/.githooks/check-branch-name.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script checks if the current branch name follows the specified format. # It's designed to be used as a 'pre-commit' git hook. diff --git a/.githooks/check-commit-msg.sh b/.githooks/check-commit-msg.sh index f87749a..6fbc251 100755 --- a/.githooks/check-commit-msg.sh +++ b/.githooks/check-commit-msg.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script checks if a commit message follows the specified format. # It's designed to be used as a 'commit-msg' git hook. @@ -25,32 +25,31 @@ COMMIT_MSG_FILE=$1 # --- Automated Commit Detection --- -# Git directory (.git/) -GIT_DIR=$(git rev-parse --git-dir) -# Check for a merge commit -if [ -f "$GIT_DIR/MERGE_HEAD" ]; then - echo "Hook: Detected a merge commit." - # Ensure the message follows a 'Merge branch...' pattern. - first_line=$(head -n1 "$COMMIT_MSG_FILE") - if [[ ! "$first_line" =~ ^Merge.* ]]; then - echo "Error: Merge commit message should start with 'Merge'." >&2 - exit 1 - fi - exit 0 +# Read the first line (header) for initial checks +HEADER=$(head -n 1 "$COMMIT_MSG_FILE") -# Check for a squash commit (from git merge --squash) -elif [ -f "$GIT_DIR/SQUASH_MSG" ]; then - echo "Hook: Detected a squash commit. Skipping validation." +# Check for Merge commits (covers 'git merge' and PR merges from GitHub/GitLab) +# Examples: "Merge branch 'main' into ...", "Merge pull request #123 from ..." +MERGE_PATTERN="^Merge (branch|pull request|tag) .*" +if [[ "$HEADER" =~ $MERGE_PATTERN ]]; then + echo -e "${GREEN}Merge commit detected by message content. Skipping validation.${NC}" exit 0 +fi -# Check for a revert commit -elif [ -f "$GIT_DIR/REVERT_HEAD" ]; then - echo "Hook: Detected a revert commit. Skipping validation." +# Check for Revert commits +# Example: "Revert "feat: add new feature"" +REVERT_PATTERN="^Revert \".*\"" +if [[ "$HEADER" =~ $REVERT_PATTERN ]]; then + echo -e "${GREEN}Revert commit detected by message content. Skipping validation.${NC}" exit 0 +fi -# Check for a cherry-pick commit -elif [ -f "$GIT_DIR/CHERRY_PICK_HEAD" ]; then - echo "Hook: Detected a cherry-pick commit. Skipping validation." +# Check for Cherry-pick commits (this pattern appears at the end of the message) +# Example: "(cherry picked from commit deadbeef...)" +# We use grep -q to search the whole file quietly. +CHERRY_PICK_PATTERN="\(cherry picked from commit [a-f0-9]{7,40}\)" +if grep -qE "$CHERRY_PICK_PATTERN" "$COMMIT_MSG_FILE"; then + echo -e "${GREEN}Cherry-pick detected by message content. Skipping validation.${NC}" exit 0 fi -- 2.49.1 From 360f601d007041324aa36a727da598d52b6ce68a Mon Sep 17 00:00:00 2001 From: Kasper Marinus Date: Mon, 3 Nov 2025 15:23:11 +0100 Subject: [PATCH 4/5] feat: chore doesn't need ref If we detect a chore commit, we don't check for the correct ref/close footer. ref: N25B-241 --- .githooks/check-commit-msg.sh | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/.githooks/check-commit-msg.sh b/.githooks/check-commit-msg.sh index 6fbc251..cdf56fb 100755 --- a/.githooks/check-commit-msg.sh +++ b/.githooks/check-commit-msg.sh @@ -86,20 +86,24 @@ 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") +# Only validate footer if commit type is not chore +TYPE=$(echo "$HEADER" | cut -d':' -f1) +if [ "$TYPE" != "chore" ]; then + # 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]+$" + # 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" + if ! [[ "$FOOTER" =~ $FOOTER_REGEX ]]; then + error_exit "Invalid footer format.\n\nFooter must be in the format: [ref/close]: \nExample: ref: N25B-123" + fi fi # 4. If the message has more than 2 lines, validate the separator -- 2.49.1 From cb5457b6be1457a7e6fb118d0c7f8164e327cd6b Mon Sep 17 00:00:00 2001 From: Kasper Marinus Date: Mon, 3 Nov 2025 15:29:06 +0100 Subject: [PATCH 5/5] feat: check for squash commits ref: N25B-241 --- .githooks/check-commit-msg.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.githooks/check-commit-msg.sh b/.githooks/check-commit-msg.sh index cdf56fb..eacf2a8 100755 --- a/.githooks/check-commit-msg.sh +++ b/.githooks/check-commit-msg.sh @@ -53,6 +53,14 @@ if grep -qE "$CHERRY_PICK_PATTERN" "$COMMIT_MSG_FILE"; then exit 0 fi +# Check for Squash +# Example: "Squash commits ..." +SQUASH_PATTERN="^Squash .+" +if [[ "$HEADER" =~ $SQUASH_PATTERN ]]; then + echo -e "${GREEN}Squash commit detected by message content. Skipping validation.${NC}" + exit 0 +fi + # --- Validation Functions --- # Function to print an error message and exit -- 2.49.1