facebook / facebook/pyrefly

Ignore-file search walks past a linked worktree's root, so the enclosing checkout's info/exclude skips every file

Open
#4,525 0 comments 2 reactions 1 assignee Claimed by @willemkokke View on GitHub
configuration good first issue
Dominant language
Rust
Stars
7k
Forks
516
PR merge metrics
No merged PRs in 30d

Description

### Describe the Bug

Split out of #4401 at @kinto0's request — this is the ignore-file half. The hidden-directory-filter half is filed separately as #4526.

The upward search for ignore files (`.gitignore`, `.ignore`, `.git/info/exclude`) in `crates/pyrefly_util/src/globs.rs` treats the directory tree as a single hierarchy: it walks from the project root towards the filesystem root and takes the nearest of each file. A **linked git worktree**'s `.git` is a `gitdir: …` pointer *file*, not a directory, so the search walks straight past the working-tree root, finds the **enclosing checkout's** `.git/info/exclude`, and applies its patterns rooted at that enclosing checkout.

Several agent tools register their worktrees by adding a pattern like `**/.claude/worktrees/` to the main checkout's `.git/info/exclude`, to keep them out of `git status`. That pattern then matches every file inside the worktree, and the check finds nothing:

```
ignore files [/.gitignore, /path/to/main-checkout/.git/info/exclude]
No Python files matched patterns …
```

git's own semantics differ in two ways:

- A directory carrying a `.git` entry — file **or** directory — is a working-tree root. An outer repository's ignore rules never apply inside it.
- A repository's shared `info/exclude` does apply inside each linked worktree, but **relative to that worktree's own root**, reached through the `gitdir` pointer and `commondir`.

`git -C check-ignore -v src/m.py` confirms the files are not ignored.

### Reproduction

```sh
git init main && cd main
printf '**/wt/\n' >> .git/info/exclude
git worktree add .claude/worktrees/wt
cd .claude/worktrees/wt
printf '[tool.pyrefly]\nproject-includes = ["src"]\n' > pyproject.toml
mkdir src && touch src/m.py
pyrefly check # No Python files matched patterns …
```

(`git -C . check-ignore -v src/m.py` exits 1 here: git does not consider the file ignored.)

### Expected behavior

The worktree checks like any other checkout: the upward ignore-file search stops at the working-tree boundary, and the repository's shared `info/exclude` applies relative to the worktree's own root — matching `git check-ignore`'s verdicts.

I have a fix and will open a PR against this issue.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.