Here is a simple, but basically untested, pre-push hook that can check for commits made with user.name and/or user.email settings that you don't want. Modify the check() function as desired.
#! /bin/sh
#
# pre-push hook to check commits to be sent
#
# The check() function takes a commit hash ID and decides if it's OK
# (returns zero) or not (returns nonzero).
check() {
local hash="$1" ret=0
set -- $(git log --no-walk --pretty=format:"%an %ae" $hash | sed 's/ /-/g')
case "$1" in
my-name-ok) ;;
my-name-bad) echo "oops, wrong author name on commit $hash"; ret=1;;
*) echo "oops? unknown author name $1 on $hash"; ret=1;;
esac
case "$2" in
my-email-ok@my-host-ok) ;;
*) echo "oops? unknown email address $2 on $hash"; ret=1;;
esac
return $ret
}
# cheesy hack to get appropriate number of 0s, assumes we're
# on a branch that exists.
NULLHASH=$(git rev-parse HEAD | sed 's/./0/g')
# Use git rev-list to figure out which commits to check.
# We could get fancy and accumulate them and uniq-ize them,
# but probably no reason to bother.
TF=$(mktemp)
trap "rm -f \"$TF\"" 0 1 2 3 15
status=0
while read localref localhash remoteref remotehash; do
if [ "$localhash" = $NULLHASH ]; then continue; fi # --delete
if [ "$remotehash" = $NULLHASH ]; then
# creating a new name on the remote, so we don't
# know for sure what's new to them, but we'll just
# assume that `--not --remotes` is good here (!!!)
scancmd="git rev-list $localhash --not --remotes
else
scancmd="git rev-list $remotehash..$localhash"
fi
# shell loops run in subshell if we use a pipe, so use a temp file
$scancmd >$TF
while read hash; do
if check $hash; then status=1; fi
done <$TF
done
exit $status
Again, this is untested, so test it (and make any required changes to check
as there are definitely some required). The general idea here is to scan each commit before git push
sends it. When we're augmenting some existing branch in the remote, git rev-list $remotehash..$localhash
enumerates the commits we're adding.
There is a flaw here (kind of deliberate): if $remotehash
denotes some commit we don't have locally, the git rev-list
above will fail. That won't make the overall script fail, but it means they have commits you don't, and you might want to abort the git push
. You could fancy this up some more by using git rev-parse --quiet --verify
with the $remotehash
value: if we can parse it, we have the commit (or tag); if not, we don't. If we don't have it, we may be resetting the branch backwards, or both resetting it backwards and moving it forwards, as --force
would. You'll need to decide what, if anything, you'd like to do about this situation.