This is an update for people who want to find alternatives to previous solutions.
There is plenty of resources now to check contents using git pre-commit hook.
The most "famous" is probably https://pre-commit.com/
Git hooks are sometimes hard to maintain and share (even if git 2.9 introduced the core.hooksPath
config that make it easier).
I mostly work with JavaScript and I found a popular module named Husky that manages shareable hooks through a projet. I like it because it's integrated, shared and configured in my projects through my package.json
.
I also tried to find a complementary module to check my contents before commiting but I found nothing satisfying. I wanted something similar with a shared configuration (in package.json
) like this:
"precommit-checks": [
{
"filter": "\\.js$",
"nonBlocking": "true",
"message": "You’ve got leftover `console.log`",
"regex": "console\\.log"
},
{
"message": "You’ve got leftover conflict markers",
"regex": "/^[<>|=]{4,}/m"
},
{
"message": "You have unfinished devs",
"nonBlocking": "true",
"regex": "(?:FIXME|TODO)"
}
]
I finally made my own: git-precommit-checks.
You can try it if you want, otherwise you can still look for alternatives (especially if you don't work with JS).
If you still want to check your contents using a bash script, you can try a more generic approach and loop over an array of searched patterns that should stop your commit.
#! /bin/bash
# If you encounter any error like `declare: -A: invalid option`
# then you'll have to upgrade bash version to v4.
# For Mac OS, see http://clubmate.fi/upgrade-to-bash-4-in-mac-os-x/
# Hash using its key as a search Regex, and its value as associated error message
declare -A PATTERNS;
PATTERNS['^[<>|=]{4,}']="You've got leftover conflict markers";
PATTERNS['focus:\s*true']="You've got a focused spec";
# Declare empty errors array
declare -a errors;
# Loop over staged files and check for any specific pattern listed in PATTERNS keys
# Filter only added (A), copied (C), modified (M) files
for file in $(git diff --staged --name-only --diff-filter=ACM --no-color --unified=0); do
for elem in ${!PATTERNS[*]} ; do
{ git show :0:"$file" | grep -Eq ${elem}; } || continue;
errors+=("${PATTERNS[${elem}]} in ${file}…");
done
done
# Print errors
# author=$(git config --get user.name)
for error in "${errors[@]}"; do
echo -e "\033[1;31m${error}\033[0m"
# Mac OS only: use auditable speech
# which -s say && say -v Samantha -r 250 "$author $error"
done
# If there is any error, then stop commit creation
if ! [ ${#errors[@]} -eq 0 ]; then
exit 1
fi