Since switching from SVN to Git, we lost the ability to enforce our coding standards through a pre-commit
hook on the subversion server.
With Git, you only
I would rather not wait for a server-side hook to control a push.
You could setup an intermediate repo which would fetch each developer's branches very regularly and audit each new commit, sending an email if a commit fails to meet some pre-defined criteria.
You can also have pre-receive hook on the central repo, but at least the developer would be aware of a potential issue sooner.
I have experimented with this too. I don't have the code at hand at the moment, but I used one of the hooks (not pre-receive, I think it was the update one) to do a temporary checkout of the new ref. You can speed this up by having a checked out tree which you just have to update and by just doing shallow clones.
This allows access to the whole source tree and you can not only run CS on the files changed with the push, but also run the unit or smoke tests.
I also agree with some of the other comments that these tests should be kept to a minimum, because nothing is more annoying than being blocked by commit hooks. Any further checks should be happening in your CI server or deployment system.
In the Drupal project, we've recently migrated to Git and are looking at similar problems. In our case, we don't want anyone checking in a LICENSE.txt file for a module since our packaging scripts do that automatically. After some back and forth, what we came up with was a receive hook that doesn't reject a bad commit, but every time it detects a bad commit (for some definition of "bad") it automatically files a critical bug in our bug tracker. That way the code is still committed, but the module maintainer and the appropriate webmaster team both get notified immediately that something is amiss and should be fixed. You could just as easily send an email or send a tweet or whatever other notification you want.
Actually we haven't implemented that quite yet, but that's the plan we're working on as soon as our Git implementation team has time. :-)
Basically, there is no good solution for the problem you describe other than rephrasing it; instead of "block detectable violations" it becomes "report detectable violations." I think that's the best you can do.
I don't speek good 'git-anese', but in Mercurial there's a hook option called 'changegroup' that essentially checks the 'top' commit of a group of incoming commits. Maybe someone in the community can tell you if there's an equiv. of 'changegroup' for git?
https://www.mercurial-scm.org/wiki/Hook#The_changegroup_hook