FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

`npm install git+file://` during hook install inside a submodule overwrites the submodule's index · Issue #3773 · pre-commit/pre-commit · GitHub

Repository navigation

npm install git+file:// during hook install inside a submodule overwrites the submodule's index #3773

Closed

Description

search you tried in the issue tracker

GIT_INDEX_FILE, GIT_DIR, no_git_env, submodule, "unable to read", "invalid object", git+file, npm git

describe your issue

Since 4.6.1, when a language: node hook environment is installed by git commit run inside a git submodule, the submodule's index is replaced with the index of the hook repository. The commit fails and whatever was staged is lost. 4.6.0 is not affected: the reproduction below passes on 4.6.0 and on ff8541f, and fails on b1cc920 (#3719), 4.6.1 and 4.6.2.

Inside a submodule, git runs the pre-commit hook with absolute GIT_DIR and GIT_INDEX_FILE (<super>/.git/modules/<name> and <super>/.git/modules/<name>/index). #3719 changed the install to npm install ... git+file://<store clone>, and npm clones and checks out that URL with git. That git inherits GIT_INDEX_FILE, so the checkout writes the hook repository's index to the submodule's index file. store.py already runs the initial clone of the hook repository with no_git_env(). The npm install does not.

Confirm the issue on 4.6.2 using this Dockerfile:

FROM python:3.13

ARG PRE_COMMIT=pre-commit==4.6.2

RUN pip install "${PRE_COMMIT}"
RUN git config --global user.name repro \
    && git config --global user.email repro@example.com \
    && git config --global protocol.file.allow always

WORKDIR /repro

COPY <<'EOF' repro.sh
set -eu
pre-commit --version

git init -q sub
cd sub

cat > .pre-commit-config.yaml <<'YAML'
repos:
  - repo: https://github.com/rbubley/mirrors-prettier
    rev: v3.6.2
    hooks:
      - id: prettier
YAML

git add .pre-commit-config.yaml
git commit -q -m init
cd ..

git init -q super
cd super

git submodule -q add ../sub sub
git commit -q -m 'add submodule'

cd sub
pre-commit install

echo '# hello' > README.md
git add README.md
git commit -m 'trigger install from inside a submodule' || true

echo '--- submodule index (expected: .pre-commit-config.yaml, README.md)'
git ls-files -s
cat ~/.cache/pre-commit/pre-commit.log 2>/dev/null || true
EOF

CMD ["bash", "repro.sh"]
docker build -t pre-commit-submodule-repro .
docker run --rm pre-commit-submodule-repro

output of docker run (the pre-commit.log it prints at the end is in the log field below):

pre-commit 4.6.2
pre-commit installed at /repro/super/.git/modules/sub/hooks/pre-commit
[INFO] Initializing environment for https://github.com/rbubley/mirrors-prettier.
[INFO] Initializing environment for https://github.com/rbubley/mirrors-prettier:prettier@3.6.2.
[INFO] Installing environment for https://github.com/rbubley/mirrors-prettier.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
An unexpected error has occurred: CalledProcessError: command: ('/usr/lib/git-core/git', 'diff', '--staged', '--name-only', '--no-ext-diff', '-z', '--diff-filter=ACMRTUXB')
return code: 128
stdout: (none)
stderr:
    fatal: unable to read 7192ee1c223039c8ac42c8871ec7f6f8faeedebd
Check the log at /root/.cache/pre-commit/pre-commit.log
--- submodule index (expected: .pre-commit-config.yaml, README.md)
100644 7192ee1c223039c8ac42c8871ec7f6f8faeedebd 0	.github/workflows/main.yml
100644 72e8ffc0db8aad71a934dd11e5968bd5109e54b4 0	.npmignore
100644 a7d109de0c111bd5b225d20183593b283ad80516 0	.pre-commit-hooks.yaml
100644 b72762837ea636398fece3c5651f664c2ee82ffb 0	.version
100644 d86d9ea06347dbd79c04079484155ea94fa2c3ed 0	LICENSE
100644 92a483e6ca5ae20de5bae985aa1215eb658c6498 0	README.md
100644 d4083c5b452e10dc41112eae1813d9d1631024b5 0	package.json

The submodule's index now holds the files of mirrors-prettier. git read-tree HEAD in the submodule recovers it.

Confirm 4.6.0 is not affected:

docker build --build-arg PRE_COMMIT=pre-commit==4.6.0 -t pre-commit-submodule-repro:4.6.0 .
docker run --rm pre-commit-submodule-repro:4.6.0

Workaround: run pre-commit install-hooks from a shell before committing.

The closest related issues I found is #1379 which has the same fatal: unable to read <sha> after a fresh install; the cause was never found for this one.

pre-commit --version

pre-commit 4.6.2

.pre-commit-config.yaml

repos:
  - repo: https://github.com/rbubley/mirrors-prettier
    rev: v3.6.2
    hooks:
      - id: prettier

~/.cache/pre-commit/pre-commit.log (if present)

version information

pre-commit version: 4.6.2
git --version: git version 2.47.3
sys.version:
    3.13.16 (main, Oct  6 2026, 04:43:07) [GCC 14.2.0]
sys.executable: /usr/local/bin/python3.13
os.name: posix
sys.platform: linux

error information

An unexpected error has occurred: CalledProcessError: command: ('/usr/lib/git-core/git', 'diff', '--staged', '--name-only', '--no-ext-diff', '-z', '--diff-filter=ACMRTUXB')
return code: 128
stdout: (none)
stderr:
    fatal: unable to read 7192ee1c223039c8ac42c8871ec7f6f8faeedebd
Traceback (most recent call last):
  File "/usr/local/lib/python3.13/site-packages/pre_commit/error_handler.py", line 73, in error_handler
    yield
  File "/usr/local/lib/python3.13/site-packages/pre_commit/main.py", line 401, in main
    return hook_impl(
        store,
    ...<5 lines>...
        args=args.rest[1:],
    )
  File "/usr/local/lib/python3.13/site-packages/pre_commit/commands/hook_impl.py", line 275, in hook_impl
    return retv | run(config, store, ns)
                  ~~~^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/pre_commit/commands/run.py", line 445, in run
    return _run_hooks(config, hooks, skips, args)
  File "/usr/local/lib/python3.13/site-packages/pre_commit/commands/run.py", line 291, in _run_hooks
    _all_filenames(args), config['files'], config['exclude'],
    ~~~~~~~~~~~~~~^^^^^^
  File "/usr/local/lib/python3.13/site-packages/pre_commit/commands/run.py", line 271, in _all_filenames
    return git.get_staged_files()
           ~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/local/lib/python3.13/site-packages/pre_commit/git.py", line 137, in get_staged_files
    cmd_output(
    ~~~~~~~~~~^
        'git', 'diff', '--staged', '--name-only', '--no-ext-diff', '-z',
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<2 lines>...
        cwd=cwd,
        ^^^^^^^^
    )[1],
    ^
  File "/usr/local/lib/python3.13/site-packages/pre_commit/util.py", line 117, in cmd_output
    returncode, stdout_b, stderr_b = cmd_output_b(*cmd, **kwargs)
                                     ~~~~~~~~~~~~^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/pre_commit/util.py", line 111, in cmd_output_b
    raise CalledProcessError(returncode, cmd, stdout_b, stderr_b)
pre_commit.util.CalledProcessError: command: ('/usr/lib/git-core/git', 'diff', '--staged', '--name-only', '--no-ext-diff', '-z', '--diff-filter=ACMRTUXB')
return code: 128
stdout: (none)
stderr:
    fatal: unable to read 7192ee1c223039c8ac42c8871ec7f6f8faeedebd

Activity

  1. Tycorc commented on Oct 11, 2026

    This isn't limited to submodules: it happens whenever git hands the hook an absolute GIT_INDEX_FILE, which it also does for git commit -a (the temporary index.lock) and for any commit in a linked worktree (.git/worktrees/<name>/index). It needs a node hook whose environment isn't installed yet, so it shows up on a fresh cache or after a rev bump.

    Plain repo, no Docker (pre-commit 4.6.2, git 2.54, node 22):

    git init r && cd r
    printf 'repos:\n  - repo: https://github.com/rbubley/mirrors-prettier\n    rev: v3.6.2\n    hooks:\n      - id: prettier\n' > .pre-commit-config.yaml
    echo '{ "a": 1 }' > x.json
    git add -A && git commit -qm init && pre-commit install
    echo '{ "a": 2 }' > x.json
    PRE_COMMIT_HOME=$(mktemp -d) git commit -am change

    The commit aborts once the lock file holds the hook repository's index. The same steps in a git worktree add checkout commit nothing and leave git ls-files listing package.json, .pre-commit-hooks.yaml and the rest of mirrors-prettier until git read-tree HEAD.

    #3774 as it stands fixes both cases for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL