Skip to content

fix: resolve ambiguous remote branch right after base branch selection - #325

Merged
kbwo merged 2 commits into
mainfrom
fix/ambiguous-remote-branch-confirm
Aug 19, 2026
Merged

fix: resolve ambiguous remote branch right after base branch selection#325
kbwo merged 2 commits into
mainfrom
fix/ambiguous-remote-branch-confirm

Conversation

@kbwo

@kbwo kbwo commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Problem

The "⚠️ Ambiguous Branch Reference" confirmation (RemoteBranchSelector, shown when a branch name exists on multiple remotes) has two problems in the new-worktree wizard:

  • It appears even when the user already selected a base branch explicitly (including a local branch). Worktree creation also resolves the new branch name against remotes (checkout-by-name semantics), so entering a new branch name that happens to exist on two or more remotes aborts creation with AmbiguousBranchError and shows the confirmation — even though the base branch was already chosen.
  • It appears only at the very end of the wizard. Ambiguity was detected when git worktree add was about to run, i.e. after the user had already gone through creation mode, branch name, and copy settings. If the selected base branch is ambiguous, the user should be asked right after selecting it.

Investigation

Facts

Reproduced on a scratch repo with two remotes (origin, upstream) that both have feature/x and feature/x2, no local refs for them, and a local main:

  • createWorktreeEffect('../wtA', 'feature/x2', 'main') failed with Ambiguous branch 'feature/x2' found in multiple remotes: origin/feature/x2, upstream/feature/x2. Please specify which remote to use. even though the base branch main is local. The throw comes from resolving the new branch name (resolveBranchReferenceEffect(branch)) in createWorktreeEffect, not from the base branch.
  • The confirmation screen was only reachable through App's AmbiguousBranchError handler after createWorktreeEffect failed — which is why it always showed up at the end of the wizard rather than at branch selection.
  • The base-branch list built by getAllBranchesEffect() merges remote branches with the origin/ prefix stripped, so a remote-only branch is indistinguishable from a local one in the list; selecting such an entry also ran into the late confirmation.

Findings

The fix moves disambiguation to selection time and stops treating the new branch name's ambiguity as an error:

  • New WorktreeService.resolveBaseBranch() classifies a selected base branch (local / single remote / ambiguous / none) without throwing. NewWorktree calls it right after the base-branch selection: a local branch is confirmed instantly (never routed to the confirmation), and an ambiguous one shows RemoteBranchSelector immediately as a wizard step.
  • createWorktreeEffect no longer fails when the new branch name exists on multiple remotes — the user already picked the base branch, so the new branch is created from it. The single-remote checkout-by-name behavior (typing feature/x checks out origin/feature/x) is unchanged.
  • Side fix: "Use existing base branch" now creates the local branch under its short name when the base resolves to a remote ref; previously a local branch literally named origin/... could be created.
  • App's late AmbiguousBranchError handling is kept as a fallback for callers that pass an unresolved base branch.

Verification

Prerequisites — build this branch and create a scratch repo whose branch feature/x exists on two remotes but not locally:

# In the ccmanager checkout of this branch
bun install && bun run build
mkdir -p /tmp/ccm-ambiguous && cd /tmp/ccm-ambiguous
git init --bare remote1
git clone remote1 work && cd work
git commit --allow-empty -m init
git branch feature/x && git branch feature/x2
git push origin main feature/x feature/x2
git init --bare ../remote2
git remote add upstream ../remote2
git push upstream --all
git branch -D feature/x feature/x2
git fetch --all
git branch -a

Expected output of the final git branch -a: only main as a local branch; feature/x and feature/x2 appear only under remotes/origin/ and remotes/upstream/.

Steps:

  • bun run lint, bun run typecheck, and bun run test all pass (1823 tests, including new unit tests for resolveBaseBranch and the creation-time fallback).
  • Service level, against the scratch repo: createWorktreeEffect(path, 'feature/x2', 'main') succeeds and git worktree list shows the new worktree on branch feature/x2 created from main's commit (before this change it failed with AmbiguousBranchError).
  • TUI, immediate confirmation: in /tmp/ccm-ambiguous/work, run node <ccmanager-checkout>/dist/cli.js, choose "New Worktree", enter a path, and select feature/x in "Select base branch". Expected: the "⚠️ Ambiguous Branch Reference" screen listing origin/feature/x and upstream/feature/x appears immediately after this selection, before the "How do you want to create the new worktree?" step. Selecting origin/feature/x continues the wizard showing Base branch: origin/feature/x.
  • TUI, no confirmation for a local base: restart the wizard, select main as base branch, choose "Choose the branch name yourself" → "Create new branch from base branch", and enter feature/x2 as the new branch name. Expected: the ambiguous confirmation never appears, and after completing the wizard git worktree list in work shows a worktree on branch feature/x2 whose commit equals git rev-parse main.

🤖 Generated with Claude Code

kbwo and others added 2 commits August 18, 2026 22:50
Two problems with the ambiguous-remote-branch confirmation:

- It appeared even when the user had explicitly selected a base branch:
  createWorktreeEffect resolved the NEW branch name against remotes, so a
  name existing on multiple remotes failed with AmbiguousBranchError even
  though the base branch (e.g. a local branch) was already chosen.
- It appeared only at the very end of the wizard (after creation mode,
  branch name, and copy settings), because ambiguity was detected when the
  worktree was actually created.

Changes:

- Add WorktreeService.resolveBaseBranch() which classifies a selected base
  branch (local / single remote / ambiguous / none) without throwing.
- NewWorktree resolves the base branch immediately after selection and, when
  ambiguous, shows RemoteBranchSelector right away as a wizard step; local
  branches are confirmed instantly and never hit the confirmation.
- createWorktreeEffect no longer fails when the new branch name exists on
  multiple remotes: the user already picked the base branch, so the new
  branch is created from it instead.
- 'Use existing base branch' now creates the local branch under its short
  name when the base resolves to a remote ref (previously a branch literally
  named "origin/..." could be created).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kbwo
kbwo marked this pull request as ready for review August 19, 2026 13:30
@kbwo
kbwo merged commit 51626af into main Aug 19, 2026
1 check passed
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