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:
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~1remote: 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:
Fail when the check is exact or the damage hard to undo: secrets, unparseable code, unsigned commits on a protected branch (Requiring Signatures).
Warn on judgment calls: big files, long subjects. A hook that cries wolf teaches --no-verify.
Move it to CI when it is slow: test suites, container builds, dependency audits.