Merge pull request 'feat(git): add pre-push hook to reject unsigned commits' (#148) from chore/pre-push-signature-check into main

This commit was merged in pull request #148.
This commit is contained in:
2026-09-13 00:58:15 +00:00
committed by Gitea
2 changed files with 59 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env bash
# Rejects a push that would put an unsigned or bad-signature commit onto a
# branch. Root cause this guards against: GUI git clients (e.g. Gittyup)
# commit via libgit2 directly and never invoke gpg, silently ignoring
# commit.gpgsign. Bypass intentionally with `git push --no-verify`.
zero=0000000000000000000000000000000000000000
while read -r local_ref local_sha remote_ref _remote_sha; do
[ "$local_sha" = "$zero" ] && continue # branch deletion
case "$remote_ref" in refs/heads/*) ;; *) continue ;; esac
if [ "$_remote_sha" = "$zero" ]; then
range="$local_sha --not --remotes"
else
range="$_remote_sha..$local_sha"
fi
bad=""
for sha in $(git rev-list $range --); do
sig="$(git log -1 --pretty=%G? "$sha")"
case "$sig" in
N | B) bad="$bad $sha" ;;
esac
done
if [ -n "$bad" ]; then
echo "pre-push: unsigned or bad-signature commit(s) pushing to $remote_ref, refusing:" >&2
for sha in $bad; do
git log -1 --pretty=' %h %G? %s' "$sha" >&2
done
echo "Fix: git commit --amend -S (or rebase -i + amend), then push again." >&2
echo "Bypass: git push --no-verify" >&2
exit 1
fi
done
# Chain to the global/system hook this local override is shadowing.
global_hooks="$(git config --global core.hooksPath 2>/dev/null)"
[ -z "$global_hooks" ] && global_hooks="$(git config --system core.hooksPath 2>/dev/null)"
if [ -n "$global_hooks" ]; then
global_hooks="${global_hooks/#\~/$HOME}" # git stores ~ verbatim
[ -x "$global_hooks/pre-push" ] && exec "$global_hooks/pre-push" "$@"
fi
exit 0
+15
View File
@@ -36,6 +36,21 @@ If you're touching anything under `docs/manual/`, you'll also want `pandoc`,
(see [Documentation Pipeline](#documentation-pipeline)) — otherwise CI will
catch problems on push.
**Point your clone at the tracked git hooks.** `.githooks/pre-push` rejects a
push carrying an unsigned or bad-signature commit — GUI git clients (Gittyup
included) commonly commit via libgit2 and skip `commit.gpgsign` silently.
This isn't wired up automatically (most users of this config never push to
this repo), so opt in once per clone:
```fish
git config core.hooksPath .githooks
```
Bypass a specific push with `git push --no-verify` if you have a genuine
reason to. See [Secrets & Machine-Specific
Config](#secrets--machine-specific-config) if you'd rather set this from
your own `local.fish` than type it by hand.
## Issues
Issues live on the Gitea repo. Three templates cover the common cases, each