|
| 1 | +#!/usr/bin/env bash |
| 2 | +# Create a commit without running git commit hooks (avoids Cursor co-author injection). |
| 3 | +set -euo pipefail |
| 4 | + |
| 5 | +usage() { |
| 6 | + cat <<'EOF' |
| 7 | +Usage: scripts/git/commit-clean.sh -m "message" [--amend] |
| 8 | +
|
| 9 | +Stages must already reflect the desired tree (git add …). |
| 10 | +Uses git commit-tree so Cursor commit-msg hooks never run. |
| 11 | +
|
| 12 | +Environment overrides: GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL |
| 13 | +EOF |
| 14 | +} |
| 15 | + |
| 16 | +repo_root="$(git rev-parse --show-toplevel 2>/dev/null)" || { |
| 17 | + echo "error: not inside a git repository" >&2 |
| 18 | + exit 1 |
| 19 | +} |
| 20 | +cd "$repo_root" |
| 21 | + |
| 22 | +message="" |
| 23 | +amend=0 |
| 24 | +while [[ $# -gt 0 ]]; do |
| 25 | + case "$1" in |
| 26 | + -m) |
| 27 | + message="${2:-}" |
| 28 | + shift 2 |
| 29 | + ;; |
| 30 | + --amend) |
| 31 | + amend=1 |
| 32 | + shift |
| 33 | + ;; |
| 34 | + -h|--help) |
| 35 | + usage |
| 36 | + exit 0 |
| 37 | + ;; |
| 38 | + *) |
| 39 | + echo "error: unknown argument: $1" >&2 |
| 40 | + usage |
| 41 | + exit 1 |
| 42 | + ;; |
| 43 | + esac |
| 44 | +done |
| 45 | + |
| 46 | +[[ -n "$message" ]] || { |
| 47 | + echo "error: -m message is required" >&2 |
| 48 | + usage |
| 49 | + exit 1 |
| 50 | +} |
| 51 | + |
| 52 | +author_name="${GIT_AUTHOR_NAME:-$(git config user.name)}" |
| 53 | +author_email="${GIT_AUTHOR_EMAIL:-$(git config user.email)}" |
| 54 | +[[ -n "$author_name" && -n "$author_email" ]] || { |
| 55 | + echo "error: configure user.name and user.email or set GIT_AUTHOR_*" >&2 |
| 56 | + exit 1 |
| 57 | +} |
| 58 | +author_email_lc="$(printf '%s' "$author_email" | tr '[:upper:]' '[:lower:]')" |
| 59 | +author_domain_ok() { |
| 60 | + local email_lc="$1" |
| 61 | + local domain="${email_lc#*@}" |
| 62 | + [[ -z "$domain" || "$domain" == "$email_lc" ]] && return 1 |
| 63 | + case "$domain" in |
| 64 | + openai.com|*.openai.com|anthropic.com|*.anthropic.com|cursor.com|*.cursor.com|cursor.sh|*.cursor.sh|google.com|*.google.com|google.dev|*.google.dev|github.com|*.github.com|microsoft.com|*.microsoft.com|azure.com|*.azure.com|perplexity.ai|*.perplexity.ai|x.ai|*.x.ai) |
| 65 | + return 0 |
| 66 | + ;; |
| 67 | + esac |
| 68 | + return 1 |
| 69 | +} |
| 70 | +case "$author_email_lc" in |
| 71 | + diazmelgarejo@gmail.com|lawrence@cyre.me|codex@openai.com) |
| 72 | + ;; |
| 73 | + *) |
| 74 | + if ! author_domain_ok "$author_email_lc"; then |
| 75 | + echo "error: commit author email must be diazMelgarejo@gmail.com, Lawrence@cyre.me, codex@openai.com, or a well-known AI/vendor domain" >&2 |
| 76 | + exit 1 |
| 77 | + fi |
| 78 | + ;; |
| 79 | +esac |
| 80 | + |
| 81 | +if git diff-index --quiet HEAD -- 2>/dev/null && [[ "$amend" -eq 0 ]]; then |
| 82 | + if git diff-index --quiet --cached HEAD -- 2>/dev/null; then |
| 83 | + echo "error: nothing staged to commit" >&2 |
| 84 | + exit 1 |
| 85 | + fi |
| 86 | +fi |
| 87 | + |
| 88 | +tree="$(git write-tree)" |
| 89 | +if [[ "$amend" -eq 1 ]]; then |
| 90 | + parent="$(git rev-parse HEAD^)" |
| 91 | +else |
| 92 | + if git rev-parse HEAD >/dev/null 2>&1; then |
| 93 | + parent="$(git rev-parse HEAD)" |
| 94 | + else |
| 95 | + parent="" |
| 96 | + fi |
| 97 | +fi |
| 98 | + |
| 99 | +if [[ -n "$parent" ]]; then |
| 100 | + new_sha="$( |
| 101 | + printf '%s\n' "$message" | |
| 102 | + GIT_AUTHOR_NAME="$author_name" GIT_AUTHOR_EMAIL="$author_email" \ |
| 103 | + git commit-tree "$tree" -p "$parent" -F - |
| 104 | + )" |
| 105 | +else |
| 106 | + new_sha="$( |
| 107 | + printf '%s\n' "$message" | |
| 108 | + GIT_AUTHOR_NAME="$author_name" GIT_AUTHOR_EMAIL="$author_email" \ |
| 109 | + git commit-tree "$tree" -F - |
| 110 | + )" |
| 111 | +fi |
| 112 | + |
| 113 | +branch="$(git symbolic-ref --short HEAD 2>/dev/null || true)" |
| 114 | +if [[ -n "$branch" ]]; then |
| 115 | + git update-ref "refs/heads/${branch}" "$new_sha" |
| 116 | +else |
| 117 | + git update-ref HEAD "$new_sha" |
| 118 | +fi |
| 119 | + |
| 120 | +git reset --hard "$new_sha" >/dev/null |
| 121 | +echo "$new_sha" |
0 commit comments