Pre-commit
One of the cornerstones of working with git is remembering to commit your work often. Often committing makes sure that it is easier to identify and revert unwanted changes that you have introduced, because the code changes becomes smaller per commit.
However, as you hopefully already seen in the course there are a lot of mental task to do before you actually write
git commit
in the terminal. The most basic thing is of course making sure that you have saved all your changes, and
you are not committing a not up-to-date file. However, this also includes tasks such as styling, formatting, making
sure all tests succeeds etc. All these mental to-do notes does not mix well with the principal of remembering to commit
often, because you in principal have to do them every time.
The obvious solution to this problem is to automate all or some of our mental task every time that we do a commit. This
is where pre-commit hooks comes into play, as they can help us attach additional tasks that should be run every time
that we do a git commit
.
Configuration
Pre-commit simply works by inserting whatever workflow we want to automate in between whenever we do a git commit
and
afterwards would do a git push
.
The system works by looking for a file called .pre-commit-config.yaml
that we can configure. If we execute
you should get a sample file that looks like
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
the file structure is very simple:
- It starts by listing the repositories where we want to get our pre-commits from, in this case https://github.com/pre-commit/pre-commit-hooks. This repository contains a large collection of pre-commit hooks.
- Next we need to defined what pre-commit hooks that we want to get by specifying the
id
of the different hooks. Theid
corresponds to anid
in this file: https://github.com/pre-commit/pre-commit-hooks/blob/master/.pre-commit-hooks.yaml
When we are done defining our .pre-commit-config.yaml
we just need to install it
this will make sure that the file is automatically executed whenever we run git commit
❔ Exercises
-
Install pre-commit
Consider adding
pre-commit
to arequirements_dev.txt
file, as it is a development tool. -
Next create the sample file
-
The sample file already contains 4 hooks. Make sure you understand what each do and if you need them at all.
-
pre-commit
works by hooking into thegit commit
command, running whenever that command is run. For this to work, we need to install the hooks intogit commit
. Runto do this.
-
Try to commit your recently created
.pre-commit-config.yaml
file. You will likely not do anything, becausepre-commit
only check files that are being committed. Instead try to runthat will check every file in your repository.
-
Try adding at least another check from the base repository to your
.pre-commit-config.yaml
file.Solution
In this case we have added the
check-json
hook to our.pre-commit-config.yaml
file, which will automatically check that all JSON files are valid. -
If you have completed the optional module M7 on good coding practice you will have learned about the linter
ruff
.ruff
comes with its own pre-commit hook. Try adding that to your.pre-commit-config.yaml
file and see what happens when you try to commit files.Solution
This is one way to add the
ruff
pre-commit hook. We run both theruff
andruff-format
hooks, and we also add the--fix
argument to theruff
hook to try to fix what is possible.```yaml repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.4.7 hooks: # try to fix what is possible - id: ruff args: ["--fix"] # perform formatting updates - id: ruff-format # validate if all is fine with preview mode - id: ruff
-
(Optional) Add more hooks to your
.pre-commit-config.yaml
. -
Sometimes you are in a hurry, so make sure that you also can do commits without running
pre-commit
e.g. -
Finally, figure out how to disable
pre-commit
again (if you get tired of it). -
Assuming you have completed the module on GitHub Actions, lets try to add a
pre-commit
workflow that automatically runs yourpre-commit
checks every time you push to your repository and then automatically commits those changes to your repository. We recommend that you make use of- this pre-commit action for installing and running
pre-commit
- this commit action to automatically commit the
changes that
pre-commit
makes.
As an alternative you configure the CI tool provided by the creators of
pre-commit
.Solution
The workflow first uses the
pre-commit
action to install and run thepre-commit
checks. Importantly we run it withcontinue-on-error: true
to make sure that the workflow does not fail if the checks fail. Next, we usegit diff
to list the changes thatpre-commit
has made and then we use thegit-auto-commit-action
to commit those changes. - this pre-commit action for installing and running
That was all about how pre-commit
can be used to automate tasks. If you want to deep dive more into the topic you
can checkout this page on how to define your own pre-commit
hooks.