We are using the pre-commit.com framework for configuring pre-commit hooks for our python project. When staging a set of files for commit, the pre-commit hooks should be applied on the state of the repo, where these staged files are included/modified, while all modifications to unstaged files should not be included. This works well for files, which get modified, but it does not work for new files / untracked files. If I create a new file and also modify some existing files and then want to commit only the changes to the modified files, but not (yet) to the new file, the pre-commit hooks are also applied to the new file. Very often this leads to the hooks failing, since the state of the repo on which the hooks are applied is inconsistent.
Is there any configuration option / cmd line argument to pre-commit to exclude untracked files from the repo, when applying the hooks?
Is there any alternative to dealing with this problem, other than temporarily removing the new files from the repo?
I already tried to mark the new files as intended to be committed with git add -N <new_file>
, which does not help, but results in the warning:
[WARNING] Unstaged intent-to-add files detected.
Pre-commit version: 2.10.1
Example:
Consider a git repo with the following content:
|-- .git
|-- .pre-commit-config.yaml
`-- foo
`-- existing_file.py
Where the file foo/existing_file.py
has the following content:
# cat foo/existing_file.py
a = 1 + 1
Pre-commit hooks have been installed via:
pre-commit install
Pre-commit hooks are configured to run flake8:
# cat .pre-commit-config.yaml
default_language_version:
python: python3.8
default_stages: [commit]
repos:
- repo: local
hooks:
- id: flake8
name: flake8
entry: flake8
always_run: true
files: $^
language: system
Now, I made a change to the file foo/existing_file.py
and added the new file foo/new_file.py
. After these changes the files have the following content:
# cat foo/existing_file.py
a = 1 + 2
# cat foo/new_file.py
import math
Now, I want to commit the change made to foo/existing_file.py
, but not the new/untracked file foo/new_file.py
. So, I stage foo/existing_file.py
, while foo/new_file.py
remains untracked.
# git add foo/existing_file.py
# git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: foo/existing_file.py
Untracked files:
(use "git add <file>..." to include in what will be committed)
foo/new_file.py
If I try now to commit, flake8 returns an error in file foo/new_file.py
, which is not included in the commit:
# git commit
flake8...................................................................Failed
- hook id: flake8
- exit code: 1
./foo/new_file.py:1:1: F401 'math' imported but unused
your configuration side-steps the framework and always runs on all files. in this case pre-commit is just doing what you told it to do
my recommendation is to not use always_run
like you're using (also your files: $^
is better written as pass_filenames: false
)
one of the main points of the framework is it only passes the necessary files to your tools so you only lint things that are checked in, when you remove that feature you're now linting everything in the repository (even things which are not checked in)
the recommended way to use flake8 is via the following configuration:
- repo: https://github.com/PyCQA/flake8
rev: 3.9.0
hooks:
- id: flake8
disclaimer: I created pre-commit and I am the current primary maintainer of flake8
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With