Skip to content

A non-git root indexes nested git repos that are also their own roots #363

Open

Description

@iceteaSA

Problem

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?

Activity

  1. aft-alfonso commented on Sep 26, 2026

    @aft-alfonso

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions