Skip to content

Instantly share code, notes, and snippets.

@timcase
Created July 17, 2026 18:51
Show Gist options
  • Select an option

  • Save timcase/71dfd39ca756fb6303657b173ea80351 to your computer and use it in GitHub Desktop.

Select an option

Save timcase/71dfd39ca756fb6303657b173ea80351 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Drop everything from the scissors line down (git commit -v diff),
# then strip comment lines
msg=$(sed '/^# -\+ >8 -\+$/,$d' "$1" | grep -v '^#')
subject=$(printf '%s' "$msg" | head -1)
# Skip autosquash targets and merge commits — not subject to normal formatting
if [[ "$subject" =~ ^(fixup|squash|amend)\!\ ]] || [[ "$subject" == Merge\ * ]]; then
exit 0
fi
errors=()
# Subject ≤ 50 characters
len=${#subject}
if [ "$len" -gt 50 ]; then
errors+=("Subject is $len chars (max 50)")
fi
# No trailing period
if [[ "$subject" == *. ]]; then
errors+=("Subject must not end with a period")
fi
# Starts with a capital letter
if [[ ! "${subject:0:1}" =~ [A-Z] ]]; then
errors+=("Subject must start with a capital letter")
fi
# If a body is present, it must be separated by a blank line
body=$(printf '%s' "$msg" | tail -n +2)
if [ -n "$body" ]; then
second=$(printf '%s' "$msg" | sed -n '2p')
if [ -n "$second" ]; then
errors+=("Separate subject from body with a blank line")
fi
# Body lines ≤ 72 characters
line_num=0
while IFS= read -r line; do
line_num=$((line_num + 1))
[ $line_num -le 2 ] && continue # subject and blank separator
line_len=${#line}
if [ "$line_len" -gt 72 ]; then
errors+=("Line $line_num exceeds 72 chars ($line_len): \"$line\"")
fi
done <<< "$msg"
fi
# No AI attribution lines
if printf '%s\n' "$msg" | grep -qiE '^Co-Authored-By:.*(claude|anthropic|codex|openai|chatgpt|gpt-|copilot|gemini|cursor|devin)'; then
errors+=("Remove AI-generated attribution line (Co-Authored-By)")
fi
if [ ${#errors[@]} -gt 0 ]; then
echo "Commit message errors:"
for e in "${errors[@]}"; do
echo " • $e"
done
exit 1
fi
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment