rewrite-commit-messages.sh
1 #!/usr/bin/env bash 2 # Normalize a single commit message (stdin -> stdout) to conventional-commit format. 3 # Used with: git filter-branch -f --msg-filter 'scripts/rewrite-commit-messages.sh' -- --all 4 # WARNING: Rewrites history (new SHAs). After running, use: git push --force-with-lease 5 # Make a backup first: git clone --mirror . ../.dotfiles-backup.git 6 7 # Read full message first so we can split (head/tail both read stdin) 8 msg=$(cat) 9 first_line=$(echo "$msg" | head -n1) 10 rest=$(echo "$msg" | tail -n +2) 11 12 [ -z "$first_line" ] && { 13 echo 14 [ -n "$rest" ] && echo "$rest" 15 exit 0 16 } 17 18 # Apply same normalization rules as cliff.toml commit_preprocessors (order matters). 19 # Use [ \t]* for portability (BSD/macOS sed). 20 first_line=$(echo "$first_line" | sed \ 21 -e 's/^\[FIX\][ \t]*/fix: /' \ 22 -e 's/^\[UPDATE\][ \t]*/chore: /' \ 23 -e 's/^Merge pull request/chore: Merge pull request/' \ 24 -e 's/^Merge branch/chore: Merge branch/' \ 25 -e 's/^[Uu]pdates\(.*\)/chore: updates\1/' \ 26 -e 's/^[Uu]pdating/chore: Updating/' \ 27 -e 's/^Updated /chore: Updated /' \ 28 -e 's/^Added /chore: Added /' \ 29 -e 's/^Add /feat: Add /' \ 30 -e 's/^Fixed /fix: Fixed /' \ 31 -e 's/^Improved /chore: Improved /' \ 32 -e 's/^Small /chore: Small /' \ 33 -e 's/^Minor /chore: Minor /' \ 34 -e 's/^remove /chore: remove /' \ 35 -e 's/^Remove /chore: Remove /' \ 36 -e 's/^Initial /chore: Initial /' \ 37 -e 's/^Inital /chore: Initial /' \ 38 -e 's/^Changed /chore: Changed /' \ 39 -e 's/^Replaced /chore: Replaced /' \ 40 -e 's/^Replace /chore: Replace /' \ 41 -e 's/^Moved /chore: Moved /' \ 42 -e 's/^Update /chore: Update /' \ 43 -e 's/^Replacing /chore: Replacing /' \ 44 -e 's/^add /chore: add /' \ 45 -e 's/^Borrowed /chore: Borrowed /' \ 46 -e 's/^Dual /chore: Dual /' \ 47 -e 's/^i3block /chore: i3block /') 48 49 # If still not conventional (type: or type(scope):), prefix with chore: 50 if ! echo "$first_line" | grep -qE '^(feat|fix|chore|doc|refactor|perf|style|test|revert|ci)(\([^)]*\))?!?:'; then 51 first_line="chore: $first_line" 52 fi 53 54 printf '%s\n' "$first_line" 55 [ -n "$rest" ] && printf '%s\n' "$rest" 56 exit 0