Skip to content

fix: worktree-aware checkout guard, visible error toasts, worktree force-remove (DAN-12)#36

Merged
danielss-dev merged 3 commits into
mainfrom
fix/worktree-checkout-guard
Jul 7, 2026
Merged

fix: worktree-aware checkout guard, visible error toasts, worktree force-remove (DAN-12)#36
danielss-dev merged 3 commits into
mainfrom
fix/worktree-checkout-guard

Conversation

@danielss-dev

Copy link
Copy Markdown
Owner

Summary

Fixes DAN-12 — "Can not do checkout of branches nor commits" when worktrees are in use, plus the invisible worktree-remove failures.

Root cause: checkout_branch ran checkout_tree (rewriting workdir + index) before set_head, and libgit2 refuses set_head onto a branch that is HEAD of a linked worktree. The repo was left half-switched — HEAD on the old branch, files on the new one — and every later safe checkout (any branch or commit) failed with phantom conflicts prevent checkout errors until a terminal reset.

  • checkout_branch now rejects a worktree-occupied branch up front (same rule as git switch), naming the worktree path; if set_head still fails post-checkout, the workdir/index roll back scoped to the tree diff so carried-over local changes are never clobbered.
  • Topbar switcher + sidebar badge worktree-occupied branches and open that worktree's tab instead of attempting a doomed checkout.
  • Toasts get an error variant (red ✕, 4.5s) — failures no longer render with a green success check; sidebar branch ops no longer swallow errors silently.
  • Worktrees overview offers an explicit Force remove / Cancel escalation when git refuses a dirty/locked worktree; forced removal passes --force --force so locked worktrees work too.

Test plan

  • cargo test -p strand-core — 97 passed, including new regression test checkout_refuses_branch_of_linked_worktree_without_touching_workdir
  • cargo clippy -p strand-core, cargo check -p strand-tauri — clean
  • pnpm run lint (tsc) — clean

🤖 Generated with Claude Code

git2 only rejects the HEAD move at set_head — after checkout_tree has
already rewritten the workdir and index — leaving the repo half-switched
and every later safe checkout failing with phantom conflicts (DAN-12).
Check the worktree registry up front like git switch does, and roll back
the tree diff if set_head still fails after a checkout.
git requires -f -f to remove a locked worktree; a single --force already
implies discarding changes, so there is no middle step worth exposing.
…N-12)

- Toasts get an error variant (red x, longer display) — failures no
  longer flash by with a green success check, which read as the app
  doing nothing.
- Sidebar branch ops surfaced nothing on failure (console.warn only);
  they now raise an error toast.
- Branch rows in the topbar switcher and sidebar badge branches that are
  HEAD of another worktree and open that worktree's tab instead of
  attempting a checkout that is guaranteed to fail.
- Worktrees overview: a remove that git refuses (dirty/locked) arms an
  explicit Force remove / Cancel pair on the row instead of dead-ending.
@danielss-dev danielss-dev merged commit 968bb5c into main Jul 7, 2026
2 checks passed
@danielss-dev danielss-dev deleted the fix/worktree-checkout-guard branch July 7, 2026 15:38
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.

1 participant