# Git Hooks
Git hooks are a powerful development feature. While it does have its issue (e.g. enforcement issues), I still think it is a handy tool in any case. This page introduces different methods for setting up and some commonly-used scripts.
# Quickstart
There are a number of ways to get started with git hooks.
# Method 1: Set up single repo for all users (Recommended)
Use this method to set up git hooks for all your users
Add your scripts to the .githooks directory
mkdir .githooks
nano pre-commit
Make your script executable
chmod +x pre-commit
Next, add this line to your Makefile so that users can automatically set core.hooksPath in a single command
init:
git config core.hooksPath .githooks
To activate the .githooks directory, run:
make init
Recommended: Commit files to repository so that other users can use the same git hooks.
git add .githooks
git add Makefile
git commit
git push
# Method 2: Set up single repo for single user
Use this method if you do not want to share the git hooks with other users
Firstly, add your scripts to the .git/hooks directory
cd .git/hooks
nano pre-commit
Make your script executable
chmod +x pre-commit
# Method 3: Set up all repos for single user via core.hooksPath
Use this method only if your git hooks are the same for all repositories.
Create a global template directory ~/.git_template/hooks
mkdir ~/.git_template
mkdir ~/.git_template/hooks
Register the hooksPath directory with git config
git config --global core.hooksPath '~/.git_template/hooks'
Add your scripts
cd ~/.git_template/hooks
nano pre-commit
Next, make your script executable
chmod +x pre-commit
# Method 4: Set up all repos for single user via init.templatedir
Use this method only if your git hooks are the same for all repositories. Compared to Method 3, this method only provides a template so changes to git hooks in the template directory will only be effective for new git repositories.
Create a global template directory ~/.git_template
mkdir ~/.git_template
mkdir ~/.git_template/hooks
Register the template directory with git config
git config --global init.templatedir '~/.git_template'
Add your scripts
cd ~/.git_template/hooks
nano pre-commit
Next, make your script executable
chmod +x pre-commit
Now, whenever you run the git init or git clone command, the scripts that you've set up should be added to the local .git/hooks directory. You can also check by running:
ls -l .git/hooks
# Recipes
# Runs linter and tests before committing changes
#!/bin/bash
# Runs linter and tests before committing changes
# Ensures that script exits if error is detected
set -e
# Use virtual environment
source venv/bin/activate
# Checks and tests
make lint
make test
# Prepends issue number before committing
#!/bin/bash
# Prepends the ticket/issue identifier in the commit message
# based on the prefix of the branch. Note that this means all
# branches MUST include the ticket/issue identifier as a prefix.
#
# Example:
# abc-123 -> ABC-123
# abc-123-this-is-a-new-branch -> ABC-123
# feature/abc-123-new-branch -> ABC-123
#
# This script was adapted from:
# https://medium.com/@nicklee1/prepending-your-git-commit-messages-with-user-story-ids-3bfea00eab5a
# Include any branches for which you wish to disable this script
if [ -z "$BRANCHES_TO_SKIP" ]; then
BRANCHES_TO_SKIP=(master develop staging test)
fi
# Get the current branch name and check if it is excluded
BRANCH_NAME=$(git symbolic-ref --short HEAD)
BRANCH_EXCLUDED=$(printf "%s\n" "${BRANCHES_TO_SKIP[@]}" | grep -c "^$BRANCH_NAME$")
# Extract ticket name and check if ticket in commit msg
TICKET_NAME=$(echo $BRANCH_NAME | sed -E -e 's:^([A-Za-z0-9_\/]*\/)*([A-Za-z0-9_]*-[0-9]*)(.*):\2:' -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/')
TICKET_IN_COMMIT=$(grep -c "$TICKET_NAME" $1)
# If it isn't excluded or already in commit message, prepend the ticket name to the given message
if [ -n "$BRANCH_NAME" ] && ! [[ $BRANCH_EXCLUDED -eq 1 ]] && ! [[ "$TICKET_IN_COMMIT" -eq 1 ]]; then
sed -i.bak -e "1s:^:[$TICKET_NAME] :" $1
fi