Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions hooks/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/bin/bash
# Git hook to enforce standardized commit message format: ZIR-XXX: Description
# This hook validates that commit messages follow the required format

COMMIT_MSG_FILE=$1

# Read only the first line (subject line) of the commit message
FIRST_LINE=$(head -n 1 "$COMMIT_MSG_FILE")

# Define the required pattern: ZIR-XXX: Description
# Where XXX is one or more digits (must be at least 1)
PATTERN="^ZIR-[0-9]+: .+"

# Check if this is a merge commit (starts with "Merge")
if echo "$FIRST_LINE" | grep -q "^Merge"; then
exit 0
fi

# Check if this is a revert commit (starts with "Revert")
if echo "$FIRST_LINE" | grep -q "^Revert"; then
exit 0
fi

# Skip validation for empty commits or comments
if [ -z "$FIRST_LINE" ] || echo "$FIRST_LINE" | grep -q "^#"; then
exit 0
fi

# Validate the commit message format (first line only)
if ! echo "$FIRST_LINE" | grep -qE "$PATTERN"; then
echo "ERROR: Commit message does not follow the required format."
echo ""
echo "Expected format: ZIR-XXX: Description"
echo " - ZIR-XXX where XXX is the issue/task number"
echo " - Followed by a colon and space"
echo " - Then a descriptive message"
echo ""
echo "Examples:"
echo " ZIR-123: Add new feature for user authentication"
echo " ZIR-456: Fix memory leak in connection pool"
echo ""
echo "Your commit message (first line):"
echo "$FIRST_LINE"
echo ""
exit 1
fi

exit 0
43 changes: 43 additions & 0 deletions hooks/prepare-commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/bash
# Git hook to auto-normalize commit messages by prepending 'ZIR-000: '
# when the message lacks a ZIR- prefix. Runs before commit-msg validation.

COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2

# Skip for merge and squash sources — those messages are auto-generated
if [ "$COMMIT_SOURCE" = "merge" ] || [ "$COMMIT_SOURCE" = "squash" ]; then
exit 0
fi

# Read the first non-comment, non-empty line
FIRST_LINE=$(grep -v '^#' "$COMMIT_MSG_FILE" | grep -v '^[[:space:]]*$' | head -n 1)

# Nothing to normalize if the message is empty
if [ -z "$FIRST_LINE" ]; then
exit 0
fi

# Skip merge and revert commits (identified by conventional prefixes)
if echo "$FIRST_LINE" | grep -qE "^(Merge|Revert) "; then
exit 0
fi

# Already conforming — nothing to do
if echo "$FIRST_LINE" | grep -qE "^ZIR-[0-9]+: "; then
exit 0
fi

# Prepend 'ZIR-000: ' to the first line in-place using a temp file
TMPFILE=$(mktemp)
awk -v prefix="ZIR-000: " '
!done && /^[^#]/ && /[^[:space:]]/ {
print prefix $0
done = 1
next
}
{ print }
' "$COMMIT_MSG_FILE" > "$TMPFILE"
mv "$TMPFILE" "$COMMIT_MSG_FILE"

exit 0
29 changes: 29 additions & 0 deletions scripts/setup-git-hooks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash
# Install tracked git hooks into .git/hooks/.
# Idempotent: safe to run multiple times.

set -euo pipefail

REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
HOOKS_SRC="$REPO_ROOT/hooks"
HOOKS_DST="$REPO_ROOT/.git/hooks"

if [ ! -d "$HOOKS_DST" ]; then
echo "ERROR: .git/hooks directory not found. Are you inside a git repository?"
exit 1
fi

for hook in commit-msg prepare-commit-msg; do
src="$HOOKS_SRC/$hook"
dst="$HOOKS_DST/$hook"

if [ ! -f "$src" ]; then
echo "WARNING: $src not found, skipping."
continue
fi

ln -sf "$src" "$dst"
echo "Installed $hook -> $dst"
done

echo "Git hooks installed successfully."
Loading