.githooks/pre-push
Ref: Size: 2.1 KiB History
#!/usr/bin/env bash # # pre-push — the merge gate. Any push that updates the shared `main` branch must # carry a RETRO.md line and pass `make ci` first (the same gate CI enforces). # This is the guard that was missing when work merged to main red. # # Scope: ONLY pushes that update the remote refs/heads/main are gated. Feature- # branch pushes and branch deletions run free. In a genuine emergency, bypass # with `git push --no-verify`. # # Enable once per clone with: make hooks set -euo pipefail protected="refs/heads/main" zero="0000000000000000000000000000000000000000" # git feeds pre-push one line per ref being pushed: # <local ref> <local oid> <remote ref> <remote oid> gate=0 range="" while read -r _local_ref local_oid remote_ref remote_oid; do [ "$remote_ref" = "$protected" ] || continue # not touching main [ "$local_oid" = "$zero" ] && continue # deleting main — nothing to test gate=1 # What this push actually adds. A remote that does not have main yet reports # the zero oid, and there is no range to diff — fall back to the last commit, # which is all a first push can be asked for. if [ "$remote_oid" = "$zero" ]; then range="$local_oid~1..$local_oid" else range="$remote_oid..$local_oid" fi done [ "$gate" -eq 1 ] || exit 0 # One line per push, not per commit: a push of eight commits owes one retro, and # the range is the whole push. The gate is the ritual, not the prose — it cannot # tell an honest line from a space. It only makes sure the moment is not skipped. if ! git diff --name-only "$range" | grep -qx RETRO.md; then echo >&2 echo "pre-push: BLOCKED — nothing in this push touches RETRO.md." >&2 echo " Append one line to RETRO.md: what slowed this work down." >&2 echo " Then commit or amend it, and push again (override: git push --no-verify)." >&2 exit 1 fi echo "pre-push: '$protected' is being updated — running 'make ci' (bypass: git push --no-verify)" if ! make ci; then echo >&2 echo "pre-push: BLOCKED — 'make ci' failed. Fix it, or override with 'git push --no-verify'." >&2 exit 1 fi echo "pre-push: make ci is green — allowing the push to $protected"