🤖 fix: delete local branch on workspace delete #1292
+254
−20
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This changes workspace deletion for local worktree workspaces to also delete the associated local git branch.
git branch -d(safe; only deletes if merged)git branch -Dmain) or branches still checked out elsewhereUI copy is updated (desktop + mobile) so users understand that deleting a workspace also deletes the branch.
📋 Implementation Plan
Plan: Delete workspace also deletes its git branch
Summary (what will change)
Behavior details (per decisions captured):
git branch -d <branch>(only deletes if git considers it merged).git branch -D <branch>(matches existingforce: truesemantics).origin/<branch>.Net LoC estimate (prod code): ~80–140 LoC (mostly
WorktreeRuntime+ UI copy).Current behavior (confirmed in repo)
WorkspaceContext.removeWorkspace()→api.workspace.remove()→workspaceService.remove()→runtime.deleteWorkspace()WorktreeRuntime.deleteWorkspace()already does best-effort branch deletion, but only when the workspace name starts withagent_.SSHRuntime.deleteWorkspace()deletes the remote directory only (no explicitgit branch -d/-D).Recommended approach
1) Backend: generalize branch deletion in
WorktreeRuntime.deleteWorkspaceFiles:
src/node/runtime/WorktreeRuntime.tssrc/node/git.tsSteps:
Change the branch-deletion gate
shouldDeleteBranch = !isInPlace && workspaceName.startsWith("agent_")shouldDeleteBranch = !isInPlace(delete branch for all worktree workspaces, not justagent_*).Add safety checks before deleting the branch (defensive, and errs on “skip deletion” rather than “delete the wrong thing”):
await listLocalBranches(projectPath)): skip.detectDefaultTrunkBranch(projectPath)) or the current branch in the main worktree (getCurrentBranch(projectPath)): skip.git -C <projectPath> worktree list --porcelainand see if any remaining worktree reportsbranch refs/heads/<name>): skip.Deletion command
deleteFlagbehavior:force=false→git branch -d "<branch>"force=true→git branch -D "<branch>"Keep deletion best-effort
git branch -dfailed).2) UI: update delete UX copy to reflect branch deletion
Goal: make it obvious that “Delete” now also targets the branch.
Files / call sites to update:
src/browser/utils/commands/sources.ts(confirm("Remove current workspace…"))src/browser/components/ArchivedWorkspaces.tsxtooltip/copy around “Delete permanently”src/browser/components/ForceDeleteModal.tsxwarning text (“Force delete” should mention branch deletion too)mobile/src/screens/ProjectsScreen.tsxdelete confirmation + force delete wordingCopy guidance:
3) Tests
Unit tests (
src/node/runtime/WorktreeRuntime.test.ts)agent_branch:force=true) removes the branch.force=false) on a merged branch:-d.maincan be deleted as a worktree, butmainbranch must not be deleted.Integration test (optional but valuable)
tests/ipc/removeWorkspace.test.tsforlocalruntime:{ options: { force: true } }, assertgit branch --list <branch>is empty in the main repo.Alternatives considered (not recommended for this iteration)
Add a “keep branch” checkbox / option to workspace.remove
Delete only “Mux-created” branches (e.g. track whether branch existed at creation time)
Given the explicit desire for “delete means delete” now that archiving exists, the simplest consistent behavior is: delete branch by default, with strong guardrails and clear UI copy.
Generated with
mux• Model:openai:gpt-5.2• Thinking:xhigh