How Worktrunk Manages Multiple Git Worktrees Efficiently: A Deep Dive into the Repository Architecture
Worktrunk manages multiple Git worktrees efficiently by treating them as first-class resources with centralized caching, branch-first resolution, and atomic removal operations in src/git/repository/worktrees.rs.
Worktrunk is a Rust-based CLI tool that streamlines Git worktree operations through a unified Repository abstraction. To manage multiple Git worktrees efficiently, the codebase implements a branch-first resolution model combined with aggressive caching in RepoCache and careful edge-case handling for submodules, symlinks, and prunable entries.
Centralized Worktree Caching with list_worktrees
Worktrunk eliminates redundant Git invocations by maintaining a single source of truth for worktree state. The Repository::list_worktrees method executes git worktree list --porcelain once per operation cycle, parsing the porcelain output into WorktreeInfo structs and filtering out bare repository entries.
The implementation caches the result in RepoCache, ensuring subsequent callers receive a read-only slice (&[WorktreeInfo]) without re-invoking Git. This guarantees consistent views across all worktree queries while minimizing subprocess overhead.
According to the source code at src/git/repository/worktrees.rs (lines 35-44), the cached list remains immutable for the duration of the command execution, preventing race conditions during concurrent operations.
Branch-First Resolution Logic
Worktrunk resolves user-supplied selectors using a hierarchical priority system in Repository::resolve_worktree and Repository::resolve_selector. The algorithm first attempts branch name resolution via worktree_for_branch, then falls back to path lookup through worktree_at_input_path.
This branch-first approach means that a branch name uniquely identifies a worktree whenever possible, while still supporting detached HEAD worktrees or multiple check-outs via explicit paths. The resolution logic handles special selectors including @ (current worktree), - (previous), and ^ (parent), with robust path normalization via canonicalize to handle symlinks and alternate root paths correctly.
The implementation at lines 98-124 of src/git/repository/worktrees.rs enforces this resolution order consistently across all Worktrunk commands.
Duplicate Branch Detection
When users force duplicate branch checkouts with git worktree add --force, Worktrunk detects the collision through warn_duplicate_checkout. This method scans the cached worktree list for branches present in multiple paths and emits a warning showing the first worktree that will be used, along with commands to remove duplicates.
Located at lines 136-156, this protection triggers once per process without imposing additional runtime cost on standard operations. The warning surfaces silent ambiguities that could otherwise cause operations to target unexpected worktrees.
Robust Path Normalization
Path comparison reliability is critical for commands like wt @ (current worktree). Worktrunk uses canonicalize combined with helper functions resolve_input_path and paths_match to compare worktree paths across symlinks and different spellings.
This normalization ensures that operations resolve correctly even on platforms with alternate root paths or case-insensitive filesystems. The path handling logic (lines 24-33) guarantees that relative inputs, absolute paths, and symbolic links all resolve to canonical representations before comparison.
Prunable and Unusable Worktree Detection
Before operating on any worktree, Worktrunk verifies usability through worktree_is_unusable. This method performs two critical checks:
- Filesystem existence verification to detect deleted directories
- Git prunable status inspection to identify stale registrations
implemented at lines 48-56, this validation prevents TOCTOU (time-of-check-time-of-use) bugs by ensuring commands never operate on entries marked for pruning by Git, even if the filesystem path technically exists.
Safe Removal and Race Condition Prevention
Worktrunk deliberately avoids git worktree prune because it indiscriminately deletes all stale entries. Instead, the prune_worktree_entry method targets specific paths using git worktree remove <path>, serialized through a repository-wide lock (worktree_registry_write) to prevent race conditions during concurrent removals.
The higher-level remove_worktree function (lines 86-104) handles submodule complexities by injecting --force when submodules are present, then rerunning cleanliness checks immediately before the destructive command. This two-phase verification guarantees safety while allowing automated cleanup of complex worktrees.
Primary Worktree Abstractions
Functions primary_worktree and home_path centralize the notion of a "main" location, returning the repository root for standard repositories or the default-branch worktree for bare repos. These abstractions (lines 58-70) eliminate redundant path computations across commands that need to change to a sensible base directory.
The implementation handles both traditional and bare repository layouts transparently, ensuring scripts and interactive usage always have a reliable reference point.
Summary
- Cached Listings:
list_worktreesparsesgit worktree list --porcelainonce intoRepoCache, returning&[WorktreeInfo]for consistent, fast access. - Branch-First Resolution:
resolve_worktreechecks branch names before paths, supporting@,-, and^selectors with canonical path matching. - Duplicate Protection:
warn_duplicate_checkoutalerts users when--forcecreates ambiguous branch-to-worktree mappings. - Safety Checks:
worktree_is_unusablefilters prunable entries and deleted paths before operations. - Atomic Removal:
remove_worktreeuses path-specific pruning withworktree_registry_writelocks, avoiding the destructivegit worktree prunecommand. - Path Normalization:
resolve_input_pathandpaths_matchhandle symlinks and platform differences reliably.
Frequently Asked Questions
How does Worktrunk cache worktree information for performance?
Worktrunk calls git worktree list --porcelain exactly once per command execution through Repository::list_worktrees, storing parsed WorktreeInfo structs in RepoCache. Subsequent lookups receive a read-only slice (&[WorktreeInfo]), eliminating subprocess overhead and ensuring all operations see a consistent worktree state.
What happens if the same branch exists in multiple worktrees?
When detecting duplicate branch checkouts (possible only with git worktree add --force), Worktrunk triggers warn_duplicate_checkout to display a warning showing which worktree will be used and how to remove duplicates. This prevents silent operation on the wrong directory without blocking execution.
How does Worktrunk handle removal of worktrees containing submodules?
The remove_worktree function automatically detects submodules and injects the --force flag to Git, then performs final cleanliness checks immediately before deletion. This approach safely handles submodule complexity while avoiding the indiscriminate cleanup of git worktree prune, using repository-wide locks to prevent race conditions during concurrent removals.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →