Reputation: 1089
I am trying to create a git server hook so that unformatted code would not be pushed. In my scenario I want to use clang format to check if the code is formatted correctly. if not the user will receive a message stating they need to format the code before pushing.
we are trying to implement a must format policy at work and this will simply be a safety net.
Upvotes: 5
Views: 4881
Reputation: 77112
It took me quite a while to piece together from the sparse examples I was able to find, so I figure I'll share what I've come up with as well.
Basically here's what you need to do:
update
hook (similar to pre-receive
)git status --work-tree=... --git-dir=...
)Although the pre-receive
hook is much more googleable, I find that the update
hook is both easier to use and more flexible. I'm using Prettier in this example, but I tried to write to be easy to adapt to any linter / vetter / formatter.
In my case my git user's home directory is /srv/git-repositories
and the hooks for the project I've set up are at:
/srv/git-repositories/my-project.git/hooks/update
I've actually tested this, so I know that it works, although it's a bit watered down from what I'm really using.
That said, it covers the basics:
ref_name=$1
new_rev=$3
# only check branches, not tags or bare commits
if [ -z $(echo $ref_name | grep "refs/heads/") ]; then
exit 0
fi
# don't check empty branches
if [ "$(expr "${new_rev}" : '0*$')" -ne 0 ]; then
exit 0
fi
# Checkout a copy of the branch (but also changes HEAD)
my_work_tree=$(mktemp -d -t git-work-tree.XXXXXXXX) 2>/dev/null
git --work-tree="${my_work_tree}" --git-dir="." checkout $new_rev -f >/dev/null
# Do the formatter check
echo "Checking code formatting..."
pushd ${my_work_tree} >/dev/null
prettier './**/*.{js,css,html,json,md}' --list-different
my_status=$?
popd >/dev/null
# reset HEAD to master, and cleanup
git --work-tree="${my_work_tree}" --git-dir="." checkout master -f >/dev/null
rm -rf "${my_work_tree}"
# handle error, if any
if [ "0" != "$my_status" ]; then
echo "Please format the files listed above and re-commit."
echo "(and don't forget your .prettierrc, if you have one)"
exit 1
fi
Although I typically use gitea for git hosting, I've tested this particular hook with a simple automated git deploy with ssh, and it should work just as well with GitLab, Gogs, and the like.
I offer a little more detail in the blog post I wrote on the matter:
You may also benefit from some of these other resources:
pre-receive
hook for clang-format (already linked above)Upvotes: 3
Reputation: 1328562
On the client side, you can look at wangkuiyi/7379a242f0d4089eaa75
which is Git pre-commit
hook that invokes clang-format
to reformat C/C++/Objective-C source code.
That gives you an idea on how to write a server-side pre-receive
hook, which will do the same and compare the resulting content with the original content.
See more at "Git 'pre-receive' hook and 'git-clang-format' script to reliably reject pushes that violate code style conventions"
Upvotes: 3