Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to exclude untracked / new files from pre-commit hook via pre-commit.com?

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

like image 659
eL_BaRTo Avatar asked Oct 17 '25 19:10

eL_BaRTo


1 Answers

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

like image 66
Anthony Sottile Avatar answered Oct 20 '25 09:10

Anthony Sottile