Skip to content

fix(discover): a .gitignore never hides a file git tracks - #2608

Merged
DeusData merged 2 commits into
mainfrom
fix/gitignore-tracked-files
Oct 12, 2026
Merged

DeusData merged 2 commits into
mainfrom
fix/gitignore-tracked-files

Conversation

@DeusData

Copy link
Copy Markdown
Owner

What

Discovery applied .gitignore rules to every path. git applies them to untracked paths only, so a tracked file can match an ignore pattern and still be part of the repository.

Real case: kubernetes-sigs/cluster-api has test/infrastructure/docker/.gitignore with the line manager, meant for a built binary. It also hid the tracked config/manager/ kustomization and the Deployment its overlays point at.

Fix (src/discover/discover.c)

  • When the indexed directory is in a git repository, discovery reads git -C <root> ls-files -z once (through cbm_popen_git, as git_context.c does). It keeps two sets: tracked paths, and every directory above one.
  • A directory that git's own rules ignore (.gitignore files, info/exclude, the global excludes file) is still entered when it holds tracked files.
  • Inside such a directory, untracked files and directories stay ignored, as in git.
  • A tracked file is kept even when a rule matches it.
  • Unchanged: the built-in skip list, .cbmignore and the size cap. With no repository, or if git fails, behaviour is exactly as before.
  • should_skip_directory becomes directory_verdict (keep / skip / git-ignored). Untracked paths get the same verdicts as before, including the .cbmignore negation of a global-excludes match.

Evidence (17 infra corpora, before = main, after = this branch)

Oracle: git ls-files -ci --exclude-standard, the tracked files an ignore rule matches. It lists 34 existing files in 7 corpora.

File nodes added 26, all in the oracle (none untracked)
File nodes removed 0
oracle files still not indexed 8, none of them for an ignore reason: .tfvars / .gitkeep have no language (0 of 240 .tfvars are indexed on main), and 5 sit under vendor/, which is on the built-in skip list

Graph gains:

  • cluster-api: the config/manager kustomization, +4 Resources, +8 CONFIGURES, and the overlay's IMPORTS now resolve.
  • helm-charts: +1 Chart.
  • otel-demo: +1 Route.
  • k8s.io: +6 Files.

Test

discover_gitignore_never_hides_tracked_files (suite discover) builds a real git repository:

  • a .gitignore with manager and *.gen.go;
  • tracked files inside the ignored directory, including one in a deeper subdirectory;
  • an untracked file and an untracked subdirectory beside them;
  • a tracked and an untracked *.gen.go.

It fails without the fix (ASSERT(manager_found)).

Not in this PR

The test-impact inventory filter (inventory_filter.c) applies the same ignore rules to its git ls-tree rows, which are all tracked. That divergence is safe: a changed file missing from its ledger falls back to running every test. It is noted as a follow-up.

git applies ignore rules to untracked paths only, but discovery applied
them to every path. A nested .gitignore line `manager`, meant for a
built binary, hid cluster-api's tracked config/manager/ kustomization,
and with it the Deployment its overlays point at.

When the indexed directory is in a git repository, discovery now reads
`git ls-files -z` once. A directory that git's rules ignore (.gitignore
files, info/exclude, the global excludes file) is still entered when it
holds tracked files. Inside it, untracked files and directories stay
ignored, as in git. A tracked file is kept although a rule matches it.
The built-in skip list, .cbmignore and the size cap apply as before. If
git cannot run, nothing changes.

On the 17 infra corpora git lists 34 tracked files that an ignore rule
matches. The fix indexes 26 of them, all from that list. The other 8 are
never indexed for other reasons: no language (.tfvars, .gitkeep) or a
built-in skip directory (vendor/). No file is lost and no untracked
file appears. cluster-api gains the manager kustomization (4 Resources,
its overlay IMPORTS), helm-charts a Chart, and otel-demo a Route.

Test: discover_gitignore_never_hides_tracked_files builds a real git
repository. It fails without the fix.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Discovery reads the tracked-file set through the supervised subprocess
API instead of cbm_popen, so no shell parses the command:

- git is resolved to an absolute path from absolute PATH entries only
  (cbm_test_impact_find_git), never the current directory;
- the repository path is a single argv entry;
- the child environment drops repository-local variables, so an
  inherited GIT_DIR cannot redirect -C;
- core.fsmonitor is off for the call;
- stdout goes to a private mkstemp file that is read and removed.

discover.c needs no entry on the security allow-list.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData
DeusData force-pushed the fix/gitignore-tracked-files branch from 8f5fc4e to 2aeaabd Compare October 12, 2026 17:41
@DeusData
DeusData merged commit a90076a into main Oct 12, 2026
12 of 14 checks passed
@DeusData
DeusData deleted the fix/gitignore-tracked-files branch October 13, 2026 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant