codegraph init walks into node_modules correctly excluded by a NESTED (non-root) .gitignore — ~63x file blowup (509 -> 32,260 files) on v1.5.0

已关闭
#1,567 2 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
35/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
活跃
技术栈
git, node.js, typescript
领域
tooling

调研方向

Start by reading src/extraction/index.ts, especially getGitVisibleFiles() and scanDirectoryWalk(), and check which scanning path runs for index/init/sync under CODEGRAPH_DEBUG. Compare the behavior against the reported nested .gitignore and node_modules case; existing synthetic fixtures did not reproduce it, so the trigger remains unknown. Done means identifying and safely reproducing the cause of the large file-count increase, then verifying that excluded files stay excluded.

由索引模型根据 Issue 内容生成。

描述

Summary

On codegraph init . --force (v1.5.0), a re-index of an existing, previously-clean project walked into two subdirectories whose node_modules trees are correctly excluded for git itself by nested (non-root) .gitignore files — producing a ~63x file-count blowup (509 files -> 32,260 files, 8,906 nodes -> 514,456 nodes, 724,013 edges, 1.8 GB DB) before the run was manually aborted (host-resource discipline; the run was still growing).

This is a real-world regression report from an active project (boba, a torrent-search proxy stack), not a synthetic construction. I (an independent contributor, not affiliated with the project that found it) verified the root-cause evidence first-hand and spent significant effort trying to reproduce it in isolation — full details below, including a negative result that may itself help triage.

Root cause evidence (git side — confirmed first-hand)

$ git check-ignore -v frontend/node_modules
frontend/.gitignore:10:/node_modules	frontend/node_modules

$ git check-ignore -v extension/node_modules
extension/.gitignore:2:node_modules/	extension/node_modules

$ git ls-files frontend/node_modules extension/node_modules | wc -l
0

Both directories are correctly and unambiguously excluded for git by their own nested .gitignore (not the project's root .gitignore, which does not mention extension/node_modules at all — only frontend/node_modules/ is separately listed there as a belt-and-suspenders entry). Yet codegraph init . --force on v1.5.0 walked into both anyway (365 MB + 236 MB, tens of thousands of files).

The project's own codegraph version had moved from 0.9.9 (last validated 2026-06-06, 509 files / 8,906 nodes, 7 PASS / 0 FAIL) to 1.5.0 with no re-verification in between — frontend/ and extension/ (each with their own node_modules and nested .gitignore) were both added to the project after the 0.9.9 baseline, so this exclusion path had never been exercised against the newer CodeGraph version before this incident.

What I could NOT reproduce (important negative result)

I read src/extraction/index.ts on main (current HEAD, still 1.5.0 per package.json) and traced both scanning implementations:

  • getGitVisibleFiles() — the primary path, delegates to real git ls-files -z -s --recurse-submodules + git ls-files -z -o --exclude-standard, which should inherit git's own correct nested-.gitignore handling.
  • scanDirectoryWalk() — the fallback for non-git projects, which explicitly layers a ScopedIgnore matcher per directory level (comment: "Patterns in a nested .gitignore are relative to that directory... mirroring how git applies .gitignore files at every level") — this also looks correct on inspection.
  • node_modules is additionally a hardcoded DEFAULT_IGNORE_DIRS entry (src/extraction/index.ts ~line 165), applied as a bare gitignore-style pattern (node_modules/) that should match at any depth regardless of which path above is taken.

Given that, I built two synthetic fixtures and ran the actual installed v1.5.0 binary against them:

  1. A minimal 2-level fixture: root + 1 subdirectory with its own nested .gitignore excluding node_modules/ (400 files under node_modules, no root-level mention). codegraph init --force correctly indexed only the 2 real source files — did not walk into node_modules.
  2. A larger fixture mimicking the real shape more closely: root + 2 subprojects (each with its own package.json + nested .gitignore excluding node_modules/), 150 fake packages per subproject (some shipping their own .gitignore, matching how real npm packages sometimes do), .bin symlinks (also common in real npm installs) — 63 nested .gitignore files total, 960 files correctly excluded by git. codegraph init --force again correctly indexed only the 3 real source files.

So the bug is real (confirmed first-hand against the real project) but I could not trigger it in either synthetic fixture at hundreds-of-files scale with the same binary version. This suggests the trigger is scale-dependent and/or specific to something about a genuine npm install-produced tree (24,102 real files under frontend/node_modules, 13,449 under extension/node_modules in the reporting project — deeply nested transitive deps, .map/binary files, very long paths, etc.) that I judged unsafe/disproportionate to reproduce here given the same host-resource concern that caused the original report to abort its own run (this is exactly the failure mode being reported, so reproducing it at full scale would risk the same runaway walk).

Diagnostic gap found (independent of root cause — draft PR attached)

While tracing getGitVisibleFiles(), I found it has an outer catch { return null; } that silently swallows any exception (git missing, a rev-parse/ls-files timeout, a buffer overrun under load, an unreadable repo, etc.) and falls through to scanDirectoryWalk() with zero log signal, even under CODEGRAPH_DEBUG. That means there is currently no way to tell, after the fact, which of the two independent scanning implementations actually ran for a given index/init/sync — which is exactly the ambiguity that makes a report like this one hard to triage (both implementations look correct on inspection, but I can't tell you which one actually executed on the reporting host).

I've opened a small, non-behavioral draft PR adding a logDebug() call there: #TBD (linked below). It doesn't claim to fix the reported regression — it's offered as defensive hardening so a future report at this scale can confirm/rule out the fallback path in one step.

Version / environment

  • CodeGraph: 1.5.0 (confirmed via codegraph --version)
  • Reproduced git evidence on: Linux, git 2.x, real project checkout
  • Reporting project's own investigation (independent of this report): docs/QA_DISCOVERY_LEDGER.md entry CODEGRAPH-1.5.0-GITIGNORE-2026-08-18 and docs/codegraph/Status.md (2026-08-18 entry) in the boba project — I'm filing this on their behalf as an upstream contribution after independently re-verifying their git check-ignore -v evidence.

What would help

  • Any pointer to whether getGitVisibleFiles() or scanDirectoryWalk() is actually the path taken on a repo of this shape (the attached diagnostic PR would surface this going forward).
  • If you have (or can share) a way to safely reproduce against a real multi-ten-thousand-file node_modules tree, I'm happy to help narrow it down further — my synthetic attempts top out at 960 files / 63 nested .gitignore files without triggering it.
主要语言
C
星标
73.2k
派生
4.7k
平均合并
3 小时 37 分钟
30 天内合并 PR
533

环境准备

这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

colbymchenry/codegraph 的其他 Issue

查看 colbymchenry/codegraph 的全部 Issue

相似的 Issue

更多 C Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。