Skip to content

git: Keep other git roots when switching to an existing worktree - #62620

Open
somtri wants to merge 1 commit into
zed-industries:mainfrom
somtri:git-switch-worktree-keep-sibling-roots
Open

git: Keep other git roots when switching to an existing worktree#62620
somtri wants to merge 1 commit into
zed-industries:mainfrom
somtri:git-switch-worktree-keep-sibling-roots

Conversation

@somtri

@somtri somtri commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Objective

Fixes #62331

In a project with more than one git repository, switching to an existing worktree from the picker drops every other git root. Open app and deploy as one project, switch to app's existing app-feature worktree, and the project is left holding only app-feature. deploy is gone, with no warning.

Creating a worktree already handles multi-root projects. Switching has no equivalent.

Solution

do_switch_worktree treated every git work directory in the project as the source of the switch:

let path_remapping: Vec<(PathBuf, PathBuf)> = git_repo_work_dirs
    .iter()
    .map(|work_dir| (work_dir.clone(), worktree_path.clone()))
    .collect();

let mut all_paths = vec![worktree_path];

all_paths then starts from the destination alone, so sibling git roots never reach the new workspace. That is the reported bug.

A switch targets one worktree, and that worktree belongs to one repository. handle_switch_worktree now passes the repository entities through, and do_switch_worktree looks for the one whose worktrees() lists the destination path. do_create_worktree already makes that same call. That repository is the one replaced by the destination. Every other repository keeps its own work directory, and its root goes into all_paths unchanged.

The same ownership result builds path_remapping, so each repository is attributed to its own path instead of all of them to the destination. That part changes no behaviour today: path_remapping is only read when transfer_state is set, and a switch never sets it. I kept it consistent rather than leave the switch path carrying attribution it would have to unlearn later.

If no repository lists the destination path, no root is replaced.

This adds one worktrees() call per repository on the switch path. Creating a worktree already pays the same cost.

Testing

test_switch_worktree_keeps_sibling_git_repos builds a project with two separate repositories and a pre-existing linked worktree, switches to that worktree, then checks that the sibling root survives, the destination opens, and the source root is replaced.

It fails on main before the change:

sibling git root should survive the switch, got ["C:\\root\\app-feature"]
  • cargo test -p git_ui_core worktree_service::tests: 6 pass
  • cargo test -p git_ui_core: 26 pass

Tested on Windows, headless. I have not run it on macOS or Linux, and I have not tested the remote path. The change is platform independent: no cfg, and no path assumptions beyond what the surrounding code already makes.

To reproduce: open two git repositories as one project, run git worktree add in one of them, then switch to that worktree from the picker.

Self-Review Checklist:

  • I've reviewed my own diff for quality, security, and reliability
  • Unsafe blocks (if any) have justifying comments
  • Tests cover the new/changed behavior
  • Performance impact has been considered and is acceptable

Release Notes:

  • Fixed switching to an existing worktree dropping the other git repositories in a multi-root project.

do_switch_worktree remapped every git work directory onto the destination
worktree and built the new workspace's path list from that destination alone,
so switching in a multi-root project dropped every other git root.

Resolve which repository owns the destination worktree, replace only that one,
and carry the remaining git roots into the new workspace unchanged.
@cla-bot cla-bot Bot added the cla-signed The user has signed the Contributor License Agreement label Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The user has signed the Contributor License Agreement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

git: Switching to an existing worktree in a multi-root project drops the other git root folders

1 participant