Summary
The worktree branch switching endpoint incorrectly blocks switching when there are untracked files (?? status). It should only block when there are modifications to tracked files that could be lost during checkout.
Steps to Reproduce
- Create a new project with
ensureInitialCommit() (empty initial commit)
- Have untracked directories like
.automaker/, .claude/, etc.
- Generate features with
branchName fields (creates worktrees)
- Try to switch to a worktree branch via the UI
Expected Behavior
Branch switch succeeds. Untracked files are safe - git leaves them alone during checkout.
Actual Behavior
Error: Cannot switch branches: you have uncommitted changes (?? .automaker/, ?? .claude/, ?? .cursor/, ...). Please commit your changes first.
Root Cause
In apps/server/src/routes/worktree/routes/switch-branch.ts, the hasUncommittedChanges() function (lines 23-39) treats ALL git status --porcelain output as blocking changes:
async function hasUncommittedChanges(cwd: string): Promise<boolean> {
const { stdout } = await execAsync('git status --porcelain', { cwd });
const lines = stdout.trim().split('\n').filter((line) => {
if (!line.trim()) return false;
if (line.includes('.worktrees/')) return false; // Only excludes .worktrees/
return true;
});
return lines.length > 0; // ANY remaining output = blocked
}
The code doesn't distinguish between:
?? (untracked files) - safe to switch
M , A , D , etc. (modifications to tracked files) - should block
Suggested Fix
Filter out untracked files from the check:
const lines = stdout.trim().split('\n').filter((line) => {
if (!line.trim()) return false;
if (line.startsWith('??')) return false; // Untracked files are safe
if (line.includes('.worktrees/')) return false;
return true;
});
Alternatively, use git status --porcelain --untracked-files=no to exclude untracked files from the output entirely.
Summary
The worktree branch switching endpoint incorrectly blocks switching when there are untracked files (
??status). It should only block when there are modifications to tracked files that could be lost during checkout.Steps to Reproduce
ensureInitialCommit()(empty initial commit).automaker/,.claude/, etc.branchNamefields (creates worktrees)Expected Behavior
Branch switch succeeds. Untracked files are safe - git leaves them alone during checkout.
Actual Behavior
Error:
Cannot switch branches: you have uncommitted changes (?? .automaker/, ?? .claude/, ?? .cursor/, ...). Please commit your changes first.Root Cause
In
apps/server/src/routes/worktree/routes/switch-branch.ts, thehasUncommittedChanges()function (lines 23-39) treats ALLgit status --porcelainoutput as blocking changes:The code doesn't distinguish between:
??(untracked files) - safe to switchM,A,D, etc. (modifications to tracked files) - should blockSuggested Fix
Filter out untracked files from the check:
Alternatively, use
git status --porcelain --untracked-files=noto exclude untracked files from the output entirely.