Skip to content

fix: improve monorepo & worktree interaction (#33)#34

Merged
matej21 merged 3 commits intocontember:mainfrom
JanTvrdik:fix/monorepo-worktree-and-fresh-install-persistence
Mar 13, 2026
Merged

fix: improve monorepo & worktree interaction (#33)#34
matej21 merged 3 commits intocontember:mainfrom
JanTvrdik:fix/monorepo-worktree-and-fresh-install-persistence

Conversation

@JanTvrdik
Copy link
Copy Markdown
Contributor

@JanTvrdik JanTvrdik commented Mar 12, 2026

Summary

Detect the actual git repo root via git rev-parse --show-toplevel instead of assuming the project path is the repo root. In monorepo setups where the project is a subdirectory, worktrees are now created at the correct location.

Before: /projects/monorepo/app-wt/branch
After: /projects/monorepo-wt/branch/app

  • Add get_repo_root() to git module
  • Store git root and subdir in WorktreeDialog for correct path computation
  • Add worktree_path field to WorktreeMetadata for correct removal
  • Extract path computation into testable compute_target_paths() function

Test plan

  • 5 new unit tests for worktree path computation (simple repo, monorepo, nested subdir, absolute template, branch with slashes)
  • All 312 existing tests pass
  • Manual: add a monorepo subdirectory as a project, create a worktree — verify path is relative to git root
  • Manual: verify non-monorepo projects still work as before

Detect the actual git repository root via `git rev-parse --show-toplevel`
instead of assuming the project path is the repo root. In monorepo setups
where the project is a subdirectory of the git root, worktrees are now
created at the correct location.

Before: /projects/monorepo/app-wt/branch
After:  /projects/monorepo-wt/branch/app

- Add `get_repo_root()` to git module
- Store git root and subdir in WorktreeDialog for correct path computation
- Add `worktree_path` field to WorktreeMetadata for correct removal
- Extract path computation into testable `compute_target_paths()` function
- Add 5 unit tests covering simple repos, monorepos, nested subdirs,
  absolute templates, and branch name sanitization
Copilot AI review requested due to automatic review settings March 12, 2026 09:38
@JanTvrdik JanTvrdik changed the title fix: improve monorepo worktree paths & fresh install persistence fix: improve monorepo & worktree interaction (#33) Mar 12, 2026
@JanTvrdik JanTvrdik force-pushed the fix/monorepo-worktree-and-fresh-install-persistence branch from 3718fc9 to 46e88fe Compare March 12, 2026 09:39
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes git worktree path computation in monorepo setups by basing worktree creation on the actual git repository root (via git rev-parse --show-toplevel) rather than assuming the project directory is the repo root. It also fixes first-run workspace persistence by only disabling auto-save when a real backup exists, avoiding the “fresh install can’t save” scenario.

Changes:

  • Add git::get_repo_root() and use it to compute correct repo-root-relative worktree locations for monorepos.
  • Persist worktree checkout path separately from project path (WorktreeMetadata.worktree_path) and use it for reliable worktree removal/back-compat.
  • Adjust workspace load behavior so auto-save is only disabled when workspace.json.bak exists and recovery failed.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/workspace/state.rs Extends persisted worktree metadata to include a dedicated worktree_path for monorepo correctness.
src/workspace/persistence.rs Refines “disable auto-save” logic to allow saving on fresh installs while still protecting recoverable backups.
src/workspace/actions/project.rs Updates worktree creation/removal to use git repo root + stored worktree checkout path.
src/views/overlays/worktree_dialog.rs Computes both worktree checkout path and project path (subdir-aware) and adds unit tests for path computation.
src/git/repository.rs Introduces get_repo_root() implementation and a basic unit test for invalid paths.
src/git/mod.rs Re-exports get_repo_root.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/views/overlays/worktree_dialog.rs Outdated
Comment on lines 696 to 698
let (_, path) = this.get_target_paths(&branch);
this.custom_path_input.update(cx, |input, cx| {
input.set_value(&path, cx);
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When enabling “Use custom path”, the input is pre-filled with project_path (the second value from get_target_paths). In monorepo cases this includes the subdir, but later create_worktree treats the custom input as the worktree checkout path and appends subdir again, producing a duplicated subdirectory (e.g. /wt/branch/app/app). Pre-fill should use the computed worktree_path (first tuple element), or alternatively treat the custom input consistently as the project path and avoid re-appending subdir.

Suggested change
let (_, path) = this.get_target_paths(&branch);
this.custom_path_input.update(cx, |input, cx| {
input.set_value(&path, cx);
let (worktree_path, _) = this.get_target_paths(&branch);
this.custom_path_input.update(cx, |input, cx| {
input.set_value(&worktree_path, cx);

Copilot uses AI. Check for mistakes.
Comment on lines +68 to +73
let project_pathbuf = PathBuf::from(&project_path);
let git_root = git::get_repo_root(&project_pathbuf)
.unwrap_or_else(|| project_pathbuf.clone());
let subdir = project_pathbuf.strip_prefix(&git_root)
.unwrap_or(Path::new(""))
.to_path_buf();
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

subdir is computed via project_pathbuf.strip_prefix(&git_root) and falls back to "" if it fails. This can silently break monorepo detection when project_path is relative or otherwise not byte-for-byte prefixed by git_root (common on Windows due to path casing, or when git returns an absolute toplevel). Consider normalizing/absolutizing both paths (e.g., canonicalize with a fallback) and surfacing an error/warn if strip_prefix fails instead of treating it as “repo root” (subdir = "").

Copilot uses AI. Check for mistakes.
Comment thread src/views/overlays/worktree_dialog.rs Outdated
Comment on lines +842 to +846
let git_root = Path::new("/projects/myrepo");
let subdir = Path::new("");
let (wt, proj) = compute_target_paths(git_root, subdir, "../{repo}-wt/{branch}", "feature");
assert_eq!(wt, "/projects/myrepo-wt/feature");
assert_eq!(proj, "/projects/myrepo-wt/feature");
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new unit tests hard-code Unix-style absolute paths and assert against /... strings. These assertions will fail on Windows because path stringification uses \ separators (and /projects/... may not round-trip the same). To keep tests portable, build expected values with PathBuf joins and compare PathBufs (or normalize separators) rather than comparing raw strings.

Copilot uses AI. Check for mistakes.
- Fix custom path pre-fill using worktree_path instead of project_path
  to prevent duplicated subdirs in monorepos
- Normalize paths before strip_prefix for cross-platform correctness
- Make tests cross-platform by comparing Path objects instead of strings
- Pass repo_path to create_worktree_project to eliminate redundant
  get_repo_root call and handle worktree-from-worktree correctly
- Simplify map/filter/map chain in remove_worktree_project
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants