diff --git a/crates/project/src/project_settings.rs b/crates/project/src/project_settings.rs index f11263a8f70..0fc91d04ce6 100644 --- a/crates/project/src/project_settings.rs +++ b/crates/project/src/project_settings.rs @@ -494,6 +494,11 @@ pub struct GitSettings { /// /// Default: ../worktrees pub worktree_directory: String, + /// Whether to discover and monitor nested Git repositories inside the + /// workspace folder. + /// + /// Default: true + pub discover_nested_repositories: bool, } #[derive(Clone, Copy, Debug)] @@ -688,6 +693,7 @@ impl Settings for ProjectSettings { .worktree_directory .clone() .unwrap_or_else(|| DEFAULT_WORKTREE_DIRECTORY.to_string()), + discover_nested_repositories: git.discover_nested_repositories.unwrap_or(true), }; Self { context_servers: project diff --git a/crates/settings_content/src/project.rs b/crates/settings_content/src/project.rs index fbeede37871..37b1cabd32a 100644 --- a/crates/settings_content/src/project.rs +++ b/crates/settings_content/src/project.rs @@ -543,6 +543,18 @@ pub struct GitSettings { /// /// Default: ../worktrees pub worktree_directory: Option, + /// Whether to discover and monitor nested Git repositories inside the + /// opened workspace folder. When enabled, every `.git` directory found + /// during file scanning creates an active repository with its own + /// status tracking, diff bases, and branch queries. + /// + /// Disable this if your workspace contains many nested Git repositories + /// that you keep around for reference but do not actively develop in. + /// Those repositories will still be visible in the project panel but + /// will not cause background Git work. + /// + /// Default: true + pub discover_nested_repositories: Option, } #[with_fallible_options] diff --git a/crates/worktree/src/worktree.rs b/crates/worktree/src/worktree.rs index ce2f34bc78d..23e8080a305 100644 --- a/crates/worktree/src/worktree.rs +++ b/crates/worktree/src/worktree.rs @@ -274,6 +274,7 @@ struct BackgroundScannerState { changed_paths: Vec>, prev_snapshot: Snapshot, scanning_enabled: bool, + discover_nested_repositories: bool, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -1192,6 +1193,7 @@ impl LocalWorktree { paths_to_scan: Default::default(), removed_entries: Default::default(), changed_paths: Default::default(), + discover_nested_repositories: settings.discover_nested_repositories, }), phase: BackgroundScannerPhase::InitialScan, share_private_files, @@ -3242,6 +3244,13 @@ impl BackgroundScannerState { return; }; + if !parent_dir.is_empty() && !self.discover_nested_repositories { + log::debug!( + "skipping nested git repository at {dot_git_path:?} because `git.discover_nested_repositories` is disabled" + ); + return; + } + parent_dir.into() } None => { diff --git a/crates/worktree/src/worktree_settings.rs b/crates/worktree/src/worktree_settings.rs index 90fe5ba724b..864aff1422a 100644 --- a/crates/worktree/src/worktree_settings.rs +++ b/crates/worktree/src/worktree_settings.rs @@ -20,6 +20,7 @@ pub struct WorktreeSettings { pub private_files: PathMatcher, pub hidden_files: PathMatcher, pub read_only_files: PathMatcher, + pub discover_nested_repositories: bool, } impl WorktreeSettings { @@ -95,6 +96,11 @@ impl Settings for WorktreeSettings { read_only_files: path_matchers(read_only_files, "read_only_files") .log_err() .unwrap_or_default(), + discover_nested_repositories: content + .git + .as_ref() + .and_then(|git| git.discover_nested_repositories) + .unwrap_or(true), } } } diff --git a/crates/worktree/tests/integration/worktree_settings_tests.rs b/crates/worktree/tests/integration/worktree_settings_tests.rs index 0a47766f35f..ba19968d668 100644 --- a/crates/worktree/tests/integration/worktree_settings_tests.rs +++ b/crates/worktree/tests/integration/worktree_settings_tests.rs @@ -18,6 +18,7 @@ fn make_settings_with_read_only(patterns: &[&str]) -> WorktreeSettings { PathStyle::local(), ) .unwrap(), + discover_nested_repositories: true, } }