Git webhooks and git hooks are different options. We can catalog in:
- Client-Side Git Hooks
- works at developer machine level
- Server-Side Git Hooks
- works at git server machine level
- WebHooks
- works notifying the event to a external services (jenkins, travis, circleci, etc) after the event in case of git push
Your title question say "webhooks" but your question details say "pre-receive hook", so that is the first thing to clarify: As I know, there are different options that works separately.
I will show you some options to accomplish your goal:
Branch Protection
Used to protect master branch of accidental pushes.
These rules are created at the repository creation moment and usually the input parameters are just the branch name and role group. Commit message is not available in these rules.
Github sample

More details here: https://docs.github.com/en/github/administering-a-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule#about-branch-protection-rules
Bitbucket sample

webhooks
Easy way, but happen after git push event. Steps:
- configure the webhook pointing to your c.i server, in the settings section of your git platform (github in your case)
- in your c.i server create a job/task to receive the event details (a big json containing a lot of information like: repository name, branch name, author mail, commit id, commit message)
- in this job/task put your logic to evaluate if commit message follow your guidelines.
- if commit message doesn't meet your guidelines, you can:
- notify by mail
- using some privileged account, revert the commit. This is some dangerous action for my opinion because the developer work could be deleted.
- search a pull request related to commit and deny it or create another webhook just for pull request event and do the same.
Github server hook
pre-receive hook feature is available only for GitHub Enterprise
Basically this is a shell script which will run in the server of your github enterprise.
I think is similar to the git server side hooks. I found this link with steps to register, update and delete hooks:
Now, how to create the script:
The problem as I found is that git message string is not a ready to use variable. In webhooks it is!!
If you want to access to the commit message, you will need to test this
The main idea is having the commit id, you can access to some file in git server, which contains the message:
tree cfda3bf37b78aef7f4daf
parent 085bb3306e7e7
author Scott Chacon <schacon@gmail.com> 1205815931 -0700
committer Scott Chacon <schacon@gmail.com> 1240030591 -0700
I'm the message sent by the developer
If you achieve that, you could add a message to be showed when your developer performs a git push with an invalid git message:
> Counting objects: 7, done.
> Delta compression using up to 4 threads.
> Compressing objects: 100% (3/3), done.
> Writing objects: 100% (7/7), 700 bytes | 0 bytes/s, done.
> Total 7 (delta 0), reused 7 (delta 0)
> remote: error: rejecting all pushes
> To git@192.168.99.100:test.git
> ! [remote rejected] main -> main (pre-receive hook declined)
> error: commit message does not meet the rule xyz
Server-Side Git Hooks
Similar to github enterprise feature. I think that install a git server in cloud or on-premise machine is not a common practice due to the ready to use services (github, bitbucket, gitlab, etc) but it is an option.
You can find more details here
As in github enterprise server, you will not have the commit message ready to use as variable. Check this:
Client-Side Git Hooks
The same idea but at developer machine level. More details here
Basically in the .git folder of any repository in the machine of your developers, you can put these scripts.
Due that this script is shell script, you will have the same problem: git message is not a ready to use variable
References