[Bug]: indexing ignores git's global core.excludesFile
Summary
FFF honors repo-local .gitignore and .ignore, but not git's global excludes file (core.excludesFile, commonly ~/.gitignore_global). Directories a user has globally ignored are still fully indexed.
This is a correctness gap rather than a feature request, so I filed it separately from #530 (which asks for opt-in ignore control / --no-ignore). Happy to fold them together if you'd prefer.
Why it matters
Tools like Worktrunk put git worktrees inside the repo (<repo>/.worktrees/<branch>) and hide them via the global excludes file precisely to avoid editing tracked .gitignore across many repos. That works for git, so the setup looks correct — but FFF indexes every one of those files.
Every worktree file is also a near-duplicate of a real path in the main tree, so the damage is not just size: real matches get crowded out. In one repo a search for an unrelated term returned 5/5 hits from .worktrees/, and the result set was capped at 5/65836.
Measured on my workspace:
| Scope | Files |
|---|---|
| one repo, real sources | 260,197 |
same repo, .worktrees/ |
497,193 (66% of index) |
| 52 repos, total worktree duplication | 2,143,597 |
Reproduction
cd "$(mktemp -d)"
mkdir -p src .worktrees/wt1
echo x > src/hit.ts; echo x > .worktrees/wt1/hit.ts
git init -q .
printf '.worktrees/\n' > global_ignore
git config core.excludesFile "$PWD/global_ignore"
git check-ignore -q .worktrees/wt1 && echo "git: ignored" # -> git: ignoredThen index that dir and search hit:
const f = FileFinder.create({ basePath, aiMode: true }).value;
await f.waitForScan(8000);
f.fileSearch("hit").value.items.map(i => i.relativePath);Actual: .worktrees/wt1/hit.ts and src/hit.ts
Expected: src/hit.ts only — git considers .worktrees/ ignored.
Control results from the same harness, confirming the gap is specific to the global file:
| Ignore source | Honored |
|---|---|
repo-local .gitignore |
✅ |
repo-local .ignore |
✅ |
global core.excludesFile |
❌ |
Adding a repo-local .ignore with .worktrees/ drops the same query from 97 hits to 0, which confirms the walker is working correctly and only the ignore source is missing.
Notes
Observed via @ff-labs/pi-fff 0.10.6 / @ff-labs/fff-node 0.10.6 on darwin-arm64, but it looks like walker-level behavior rather than anything binding-specific. strings on libfff_c.dylib shows core.excludesfile already present, so libgit2 config reading may already be in reach.
Precedent: ripgrep reads core.excludesFile by default (--no-require-git aside), and fd does the same via the ignore crate — so honoring it would match what users expect from comparable tools.
Workaround
Repo-local .ignore restating the globally-ignored dirs; I automate it with a worktree-creation hook. Works, but needs repeating per repo.
Source: dmtrKovalenko/fff