Docs Core
Branches and worktrees
Put two tiles on one repository without them fighting over one checkout: each on its own branch, in its own folder, with the ones that have gone wrong saying so.
On this page7
All pages12
Two terminals open on one repository have always shared one working copy. A session that
starts on main and a session that runs git switch fix-the-thing are the same checkout, so
the second one moves the first, and the way that ends is a session committing to a branch
nobody pointed it at.
That is not a hypothetical once an agent is doing the switching. Pin a tile to a branch and it gets a git worktree instead: a second checkout of the same repository, on its own branch, sharing one object store with the original. Two tiles, two folders, one repo, no collision.
The branch chip
Every tile header carries the branch its folder is on, with a clean/dirty dot and ↑/↓ ahead-behind. Click it and the menu lists, in this order:
- The worktrees this repo already has, the main checkout first, each saying which it is and whether it is the one this tile is on. A folder somebody deleted in Explorer says folder missing; one git has finished with says prunable; a detached head shows the commit rather than an empty name.
- Branch with no worktree: every local branch that has nowhere to work in yet, plus the ones that exist only on a remote. Picking one makes the worktree and repoints the tile in a single go.
- New branch from
main… creates the branch from whatever the main checkout is on, and a worktree for it. - Another branch by name… is for a branch that exists here or on a remote but is too far down the list to scroll to.
The shell already running does not move
Picking a branch changes where the next terminal for this tile opens. It does not relocate the shell that is in it.
A running build, a Claude session mid-turn, a REPL with state in it all stay where they are,
and the menu says so before you pick. The tile keeps reporting where its shell actually is,
shell in dispatch-main, until you restart it, and Restart the shell in… is in the
same menu.
A worktree is not a second project
The distinction that has to stay straight:
- The project
- Which repository this tile belongs to. What the sidebar highlights, what a startup command is keyed by, what a Studio link hangs off.
- The folder
- Which checkout this tile is about. Where a new terminal opens, and whose git status the header paints.
Pinning a tile moves the second and leaves the first alone. So four tiles on four branches of one repo are still one row in the sidebar, one entry in recents, and one project startup command.
Where the folders go
By default, beside the repository they came from, named <repo>-<branch>. So a dispatch
checkout with a tile pinned to content-completeness grows a dispatch-content-completeness
next to it.
Where new worktrees go… at the bottom of the menu changes that: name a folder and every new worktree lands there instead, under the same names. Leave it empty to go back to beside the repo.
When something has gone wrong with a pin
A pinned tile is a claim about a folder on disk, and folders move. Three ways that claim goes stale, each of which the chip says out loud rather than quietly falling back:
- The worktree folder was deleted
- worktree gone, and the tile has fallen back to the project’s own checkout
- Something switched that checkout to a different branch
- pinned to
fix-the-thing, with the branch it is actually on in the full message - The shell in the tile is still in the old folder
- shell in
dispatch; restart it to move it
Read that before telling a session to commit. It is the same sentence dispatch_list returns
as branchWarning, so a lead session laying work out across branches hears it too rather
than finding out from the reflog.
Removing one
Remove this worktree… deletes the folder. A worktree with uncommitted changes in it is refused first and the message says what is in there; agreeing to it anyway removes only the working copy: the branch is kept, and everything committed to it is still in the repository.
Every tile pointed at that folder is detached, not only the one you did it from, so no tile
is left holding a cwd that no longer exists.
Detach (back to dispatch) does the smaller thing: the tile goes back to the project’s
own checkout and the worktree stays where it is.
From a plan
dispatch_plan takes a branch per tile, so a lead session can lay four tickets out across
four branches in one call:
Take BUG-114 and BUG-118 in vantage, each on its own branch off main, and open the plan next to them.
Every branch is resolved in the same all-or-nothing pass as the projects: a plan that cannot place one tile on its branch opens none of them. Within that pass, reuse comes before creation: an existing worktree for that branch is used, a branch with none gets one, and a branch that exists nowhere is created from the main checkout’s current branch. So the same plan run twice does not leave eight folders behind.
dispatch_list reports branch and, on a pinned tile, the worktree it was pinned to. See
Planning.
This is git’s own worktrees, not a copy of your repo. One object store, one set of refs, several working copies.
git worktree listin any of them shows the same set Dispatch is showing you, and removing one by hand is a thing Dispatch notices rather than a thing it breaks on.