|
1 |
| -!!! bug "Work In Progress" |
| 1 | +# Pre-commit |
2 | 2 |
|
3 |
| - This page is still being written. The content below (if any) may change. |
| 3 | +???+ abstract |
| 4 | + |
| 5 | + This guide explains what is pre-commit and how to set it up as a git hook that will run automatically before your |
| 6 | + commits. It also describes how to run pre-commit manually from the CLI, how to skip some or all of the individual |
| 7 | + checks it performs, what happens when hooks edit files and where it's configuration file is. |
| 8 | + |
| 9 | +Now that you've seen the linters, formatters, type-checkers and other tools that we use in the project, you might be |
| 10 | +wondering whether you're really expected to run all of those commands manually, after each change. And of course, no, |
| 11 | +you're not, that would be really annoying, and you'd probably also often just forget to do that. |
| 12 | + |
| 13 | +So, instead of that, we use a tool called [`pre-commit`](https://pre-commit.com/), which creates a [git |
| 14 | +hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks), that will automatically run before each commit you |
| 15 | +make. That means each time when you make a commit, all of these tools will run over the code you updated, and if any of |
| 16 | +these linters detects an issue, the commit will be aborted, and you will see which linter failed, and it's output |
| 17 | +telling you why. |
| 18 | + |
| 19 | +## Installing pre-commit |
| 20 | + |
| 21 | +To install pre-commit as a git hook all you need to do is to run: |
| 22 | + |
| 23 | +```bash |
| 24 | +pre-commit install |
| 25 | +``` |
| 26 | + |
| 27 | +This will install pre-commit as a git hook into your git repository, which will mean it will run automatically before |
| 28 | +every new commit you make. |
| 29 | + |
| 30 | +!!! warning |
| 31 | + |
| 32 | + Pre-commit itself will be installed via poetry, which means you will need to have an |
| 33 | + [activated](./setup.md#activating-the-environment) poetry environment whenever you make a new commit, otherwise, |
| 34 | + the pre-commit git hook will fail with command not found. |
| 35 | + |
| 36 | +## Hooks that modify files |
| 37 | + |
| 38 | +Sometimes, hooks can end up modifying your files, for example the ruff format hook may do so if your file wasn't |
| 39 | +already formatted by ruff. When this happens, the hook itself will fail, which will make git abort the commit. At this |
| 40 | +point, you will be left with the original changes still staged, but some files may have been modified, which means |
| 41 | +you'll want to `git add` those again, staging these automatic modifications and then make the commit again. |
| 42 | + |
| 43 | +Note that in case you were only committing a [partial change](./great-commits.md#partial-adds), which means you still |
| 44 | +had some parts of the file unstaged, pre-commit will not modify the files for you. Instead, the hook will just fail, |
| 45 | +leaving the rest up to you. You should now run the formatter yourself and perform another partial add, updating the |
| 46 | +staged changes to be compliant. |
| 47 | + |
| 48 | +## Running manually |
| 49 | + |
| 50 | +Even though in most cases, it will be more than enough to have pre-commit run automatically as a git hook, |
| 51 | +sometimes, you may want to run it manually without making a commit. |
| 52 | + |
| 53 | +!!! tip |
| 54 | + |
| 55 | + You can run this command without having pre-commit installed as a git hook at all. This makes it possible to avoid |
| 56 | + installing pre-commit and instead running all checks manually each time. That said, we heavily recommend that you |
| 57 | + instead install pre-commit properly, as it's very easy to forget to run these checks. |
| 58 | + |
| 59 | +To run pre-commit manually you can use the following command: |
| 60 | + |
| 61 | +```bash |
| 62 | +pre-commit run --all-files |
| 63 | +``` |
| 64 | + |
| 65 | +Using this command will make pre-commit run on all files within the project, rather than just running against the |
| 66 | +git staged ones, which is the behavior of the automatically ran hook. |
| 67 | + |
| 68 | +## Skipping pre-commit |
| 69 | + |
| 70 | +!!! info "Automatic skipping" |
| 71 | + |
| 72 | + Pre-commit is pretty smart and will skip running certain tools depending on which files you modified. For example |
| 73 | + some hooks only check the validity of Python code, so if you haven't modified any Python files, there is no need to |
| 74 | + run those hooks. |
| 75 | + |
| 76 | +Even though in most cases enforcing linting before each commit is what we want, there are some situations where we need |
| 77 | +to commit some code which doesn't pass these checks. This can happen for example after a merge, or as a result of |
| 78 | +making a single purpose small commit without yet worrying about linters. In these cases, you can use the `--no-verify` |
| 79 | +flag when making a commit, telling git to skip the pre-commit hooks and commit normally. When making a commit, this |
| 80 | +would look like: |
| 81 | + |
| 82 | +```bash |
| 83 | +git commit -m "My unchecked commit" --no-verify |
| 84 | +``` |
| 85 | + |
| 86 | +You can also only skip a specific hook, by setting `SKIP` environmental variable (e.g. `SKIP=basedpyright`) or even |
| 87 | +multiple hooks (`SKIP=ruff-linter,ruff-formatter,slotscheck`). When making a commit, this would look like: |
| 88 | + |
| 89 | +```bash |
| 90 | +SKIP="check-toml,slotscheck,basedpyright" git commit -m "My partially checked commit" |
| 91 | +``` |
| 92 | + |
| 93 | +!!! note "" |
| 94 | + |
| 95 | + The names of the individual hooks are their ids, you can find those in the [configuration file](#configuration) for |
| 96 | + pre-commit. |
| 97 | + |
| 98 | +!!! warning |
| 99 | + |
| 100 | + This kind of verification skipping should be used sparingly. We value a clean history which consistently follows |
| 101 | + our linting guidelines, and making commits with linting issues only leads to more commits, fixing those issues later. |
| 102 | + |
| 103 | +## Configuration |
| 104 | + |
| 105 | +You can find pre-commit's configuration the `.pre-commit-config.yaml` file, where we define which tools should be ran |
| 106 | +and how. Currently, pre-commit runs ruff linter, ruff formatter, slotscheck and basedpyright, but also a checker for |
| 107 | +some issues in TOML/YAML files. |
0 commit comments