As requested in the discussion on "Trustable guix pull" [0], I've recently started signing the commits I push to Savannah.
At first, I set "gpgsign = true" in my Guix repo's Git config. This requires you to sign every commit you make. It's effective, but I found it annoying to provide my signing key while doing exploratory hacking, rebasing a branch on master, etc. Instead, I want to sign after my final "self-review" and before pushing to Savannah or sending patches to the list for final review. So, I've attached a pre-push Git hook that should prevent unsigned commits from being pushed to any remote [1]. I've also attached a shell function that will sign commits besides HEAD (useful for signing a range of commits). I didn't find a more Git-idiomatic way to sign an existing commit besides HEAD. Please let me know if you see any problems with this approach, or if you can suggest some improvements. [0] http://debbugs.gnu.org/cgi/bugreport.cgi?bug=22883#16 [1] One could make it remote-specific if desired.
#!/gnu/store/b1yqjimbdh5bf9jnizd4h7yf110744j2-bash-4.3.42/bin/sh # A hook script that prevents the user from pushing unsigned commits. # Called by "git push" after it has checked the remote status, but before # anything has been pushed. If this script exits with a non-zero status nothing # will be pushed. # # This hook is called with the following parameters: # # $1 -- Name of the remote to which the push is being done # $2 -- URL to which the push is being done # # If pushing without using a named remote those arguments will be equal. # # Information about the commits which are being pushed is supplied as lines to # the standard input in the form: # # <local ref> <local sha1> <remote ref> <remote sha1> z40=0000000000000000000000000000000000000000 while read local_ref local_sha remote_ref remote_sha do if [ "$local_sha" = $z40 ] then # Handle delete : else if [ "$remote_sha" = $z40 ] then # New branch, examine all commits range="$local_sha" else # Update to existing branch, examine new commits range="$remote_sha..$local_sha" fi # Check if push candidate commits are PGP signed. git verify-commit $(git rev-list $range) >/dev/null 2>&1 if [ $? -ne 0 ] then echo "error: Please sign these commits before pushing:" 1>&2 echo $range 1>&2 exit 1 fi fi done exit 0
git-sign() { case $# in "0") range=HEAD ;; "1") range=$1 ;; * ) echo "too many arguments" 1>&2; return 1 ;; esac # In git-2.8.4, it should be possible to drop the -i option , # along with the override of EDITOR: # https://git.kernel.org/cgit/git/git.git/commit/?h=next&id=78ec240020db4bdd773830f3d41f4b4bdf9a4e2d EDITOR=true git rebase -i "$range" --exec "git commit --amend --no-edit --gpg-sign" \ || git rebase --abort }
signature.asc
Description: PGP signature