Skip to content

.gitignore excludes are silently skipped when the tracked root is a subdirectory of the git repository #419

Description

@pbednarcik

Summary

EffectiveExclude reads .gitignore only at the tracked root itself (statGitignore(repoPath) in internal/config/manager.go). Git applies ignore files from the repository root downward, so in the common monorepo layout — git root at repo/, gortex tracking repo/projects/App — the entire gitignore layer silently disappears. Nothing warns; the index just quietly fills with everything the ignore file was supposed to keep out.

For .NET solutions this is compounded by internal/excludes/builtin.go: Builtin covers JS (node_modules/), Python (.venv/, __pycache__/), JVM (.gradle/, target/), iOS (Pods/) — but has no Visual Studio / MSBuild entries at all. When the gitignore layer is missing, nothing catches .vs/, bin/, or obj/.

Observed on a real solution

Production .NET solution, ~10,400 indexed files, tracked root one level below the git root (whose .gitignore has standard .vs/ and [Oo]bj/ entries — verified with git check-ignore -v):

  • .vs/<Solution>/v17/HierarchyCache.v1.txt and the v18 copy indexed as first-class doc nodes
  • 50+ obj/**/project.assets.json indexed (hit the result cap)
  • generated obj/{Debug,Release}/net8.0/*.AssemblyInfo.cs indexed as real C# source — duplicate generated symbols per build configuration alongside the hand-written ones
  • obj/**/*.csproj.FileListAbsolute.txt indexed as doc nodes

Beyond wasted index size, this junk actively breaks search recall — the ranking side of that is addressed in PR #416, but the two-line version: those .vs/obj text files are stuffed with source file paths, so they outrank real classes on exactly the tokens .NET naming conventions use. Keeping them out of the index in the first place is the other half of the defense.

Repro (minimal)

git init repo && cd repo
echo "junk/" > .gitignore
mkdir -p projects/app/junk
echo "class Real {}" > projects/app/Real.cs
echo "noise" > projects/app/junk/noise.txt
gortex track projects/app   # track the subdirectory, not the git root
# index → junk/noise.txt is indexed despite being git-ignored

Suggested fix

  1. Discover the git root by walking up from the tracked root to the nearest .git, and layer every .gitignore on the path from the git root down to the tracked root (patterns re-anchored relative to the tracked root, matching git semantics).
  2. Independently, add the standard VS/MSBuild set to excludes.Builtin as defense-in-depth, same spirit as the existing Pods//.gradle/ entries: .vs/, bin/, obj/, TestResults/. (bin/ and obj/ are effectively never first-party source directories in .NET repos; a re-include via !pattern remains available for the exceptions.)

Happy to send a PR for either or both halves if that's welcome.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions