You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A non-git root indexes nested git repos that are also their own roots #363
When a project root is not a git repo but contains git repos that are also opened as their own roots, the containing root indexes and embeds every nested repo a second time.
project_walk_builder (crates/aft/src/search_index.rs:4913, at f1666ac) prunes directories named .git, but not the directory that contains one, so the walk goes straight into each nested repo's working tree. The semantic index takes its file list from the same walk (walk_project_files, see semantic_index.rs:4728).
Evidence (our install)
One workspace directory, not a repo, holds 18 git repos, each also bound as its own root.
The workspace root's lexical index held 1,841 paths of one child repo. That child's own index holds 1,842.
The workspace root's semantic.bin was 1.4 GB, and the root held 1.71 GB resident, 56% of all memory attributed to roots.
A .aftignore in the workspace root listing each child as an anchored /<repo>/ line dropped its attributed memory to 0.23 GB, live and without a restart. The child roots' indexes were unchanged.
One caveat with that workaround. Parent .aftignore rules are applied inside the child roots' walks too (parents(true)). Only anchored directory lines are safe; a glob or an unanchored name would also hide files from every child root.
Question
Should a root that isn't a git repo stop at nested .git boundaries by default, or is .aftignore the intended answer for this layout?
Thanks, this is a real gap, and your diagnosis is right. A root that isn't itself a git repo walks straight into the working trees of the repos inside it, so every child repo is indexed and embedded a second time. We measured the same thing on our own workspace folder: a 273 MB search index rebuilt 35 times in 10 hours and a 2.6-hour embedding pass, all duplicating the child repos' own indexes.
Answer to your question: .aftignore is not the intended answer. We've designed the fix. A root that isn't in a git repo but has git repos beneath it (up to 3 levels deep, at most 32 repos) builds no indexes of its own. Search, grep, glob and the call graph answer from each child repo's own index, opened read-only, and say when a child's index is out of date or missing. $HOME keeps its existing behaviour. The implementation is starting now; it will ship after 0.58.0.
Until then, your anchored /<repo>/ lines are the right workaround, and your caveat about unanchored patterns reaching the child roots is correct.
Activity
aft-alfonso commentedon Sep 26, 2026
Thanks, this is a real gap, and your diagnosis is right. A root that isn't itself a git repo walks straight into the working trees of the repos inside it, so every child repo is indexed and embedded a second time. We measured the same thing on our own workspace folder: a 273 MB search index rebuilt 35 times in 10 hours and a 2.6-hour embedding pass, all duplicating the child repos' own indexes.
Answer to your question:
.aftignoreis not the intended answer. We've designed the fix. A root that isn't in a git repo but has git repos beneath it (up to 3 levels deep, at most 32 repos) builds no indexes of its own. Search, grep, glob and the call graph answer from each child repo's own index, opened read-only, and say when a child's index is out of date or missing.$HOMEkeeps its existing behaviour. The implementation is starting now; it will ship after 0.58.0.Until then, your anchored
/<repo>/lines are the right workaround, and your caveat about unanchored patterns reaching the child roots is correct.