4 minutes
Git Hooks
tl-dr
python Django project git hooks tutorial for automating certain tasks and explanation about git hooks
What are git hooks
- Git hooks are scripts/programs that Git executes before or after a particular event occurs in a Git repository. Git hooks are a built-in feature - no need to download anything. Git hooks are run locally.
- they are placed in hooks directory to trigger actions at certain points in git’s execution. Hooks that don’t have the executable bit set are ignored.
- They let you customize Git’s internal behavior and trigger customizable actions at key points in the development life cycle. for example I want to spell-check for commit message ( I have spellophobia ) or I want to check code for PEP8 maybe before commit or I want to run migrations after taking pull if one is available its only limited to what you can imagine and trust me it will make you fast and efficient also little lazy
How do I implement Git hooks?
The short and easy: Overwrite (or create) one of the scripts in .git/hooks and make it executable.
chmod +x .git/hooks/scipt
Git hooks for improving Python Django project Flow ( if you read it it can be used for other projects too )
pre-push
it is called after git push
after it has checked the remote status, but before anything has been pushed. If this script exits with a non-zero status nothing will be pushed
we will start by creating a file in hooks folder
touch .git/hooks/pre-push
now lets edit the file and lets create a check that no one can push to master
#!/usr/bin/env bash
branch="$(git rev-parse --abberev-ref HEAD)"
if ["$branch" = "master"]; then
echo "you cannot commit to '"$(branch)"' branch"
exit 1
fi
now final step make it executable
chmod +x .git/hooks/pre-push
now whenever you will push to master it will fail it and throw you a message
post-merge ( runs after git pull
)
we will start by creating a file in hooks called post-merge. so we can do many things after a pull request like if its a node project we can check for changes in package.json and run npm install similarly for python project we can check for requirement.txt file.
I have a new idea to not run migrations for a Django project after taking pull let it run automatically and let me forget that such a command exists.
#!/usr/bin/env bash
# lets check for changed files
changed_files = "$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)"
# function to check and run if we see file we want
check_and_run() {
echo "$changed_files" | grep -i --quiet "$1" && eval "$2"
}
# using for python packages
check_and_run migration "python $(git rev-parse --show-toplevel)/manage.py migrate"
# using for checking packages and its update
check_and_run requirements.txt "pip install -r requirements.txt"
replace python and pip with the path of your virtual env
pre-commit ( this is one of the most useful hook to make sure you are not doing any mistake )
we are going to use a already available framework for this pre-commit but you can also make a file too.
-
install pre-commit:
pip install pre-commit
-
Add
pre-commit
torequirements.txt
(orrequirements-dev.txt
) -
Define
.pre-commit-config.yaml
with the hooks you want to include.repos: - repo: https://github.com/ambv/black rev: stable hooks: - id: black language_version: python3.4 - repo: https://gitlab.com/pycqa/flake8 rev: 3.7.9 hooks: - id: flake8 - repo: https://github.com/pre-commit/pre-commit-hooks rev: v3.1.0 hooks: - id: trailing-whitespace
flake is used for checking python file format you can create a config file too if you want it to be more specific
black will fix formating errors before commit
also you can find many more plug ins at pre-commit-hooks git repo
-
Execute
pre-commit install
to install git hooks in your.git/
directory.
Notes
Q: I don’t want to use hook. How to bypass it during commit ?
git commit --no-verify
# or
git commit --n
Q: I only want to run lint on diff ?
you can try a package called lint-diffs
References
https://githooks.com/ https://www.git-scm.com/doc https://github.com/aitemr/awesome-git-hooks