Fail or Warn?

When Hooks Should Fail a Commit and When They Should Warn

Client hooks are a convenience, not a control: --no-verify skips pre-commit, commit-msg and pre-push, and a clone without npm 2,036 install has no hooks at all. Rules that must hold go on the server, where pre-receive sees every pushed commit before any branch moves. Sam's fails on secrets and warns on big files:

A server-side pre-receive hook, and a push it refusesShell
cat > ../server/booknest.git/hooks/pre-receive <<'EOF'
#!/bin/sh
# booknest.git policy: reject commits that add a .env file, warn about big files
zero=0000000000000000000000000000000000000000
while read -r old new ref; do
  [ "$new" = "$zero" ] && continue                     # a deleted branch
  if [ "$old" = "$zero" ]; then range="$new --not --all"; else range="$old..$new"; fi
  for c in $(git rev-list $range); do
    git diff-tree -r --no-commit-id --diff-filter=AM "$c" |
    while read -r _ _ _ blob _ path; do
      case "$path" in .env|*/.env)
        echo "error: $(git rev-parse --short "$c") adds $path; secrets stay out of Git"
        exit 1 ;;
      esac
      size=$(git cat-file -s "$blob")
      [ "$size" -le 1048576 ] || echo "warning: $path is $size bytes; use Git LFS"
    done || exit 1
  done
done
EOF
chmod +x ../server/booknest.git/hooks/pre-receive
git add -f .env && git commit -q --no-verify -m "Add local settings"
git push -q; echo "exit status $?"
git reset -q HEAD~1
Output
remote: error: 9b0a60f adds .env; secrets stay out of Git
To ../server/booknest.git
 ! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to '../server/booknest.git'
exit status 1

Git 1,932 feeds pre-receive one line per ref, <old> <new> <refname>, with the new objects held in quarantine; if the hook fails, they are discarded and no ref moves. Its output reaches the pusher prefixed remote:. git reset -q HEAD~1 undid the local commit and kept .env on disk, ignored again. GitHub.com and GitLab.com do not run custom pre-receive scripts (their self-managed editions do); they offer rulesets and push rules instead (GitHub). Decide per rule by weighing a false alarm against a miss: