Skip to content

Commit 11591d9

Browse files
committed
fix(git): surface checkout failure details
1 parent c1470b9 commit 11591d9

2 files changed

Lines changed: 34 additions & 4 deletions

File tree

packages/server/src/__tests__/git/cli.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,32 @@ describe("runGitCheckout", () => {
953953
const { stdout } = await execFileAsync("git", ["branch", "--show-current"], { cwd: testDir });
954954
expect(stdout.trim()).toBe("feature/login-page");
955955
});
956+
957+
it("returns the underlying git error when checkout is blocked by another worktree", async () => {
958+
await writeFile(join(testDir, "README.md"), "test");
959+
await execFileAsync("git", ["add", "."], { cwd: testDir });
960+
await execFileAsync("git", ["commit", "-m", "initial"], { cwd: testDir });
961+
962+
const linkedWorktreeDir = await mkdtemp(join(tmpdir(), "git-linked-worktree-"));
963+
try {
964+
await execFileAsync("git", ["branch", "feature/worktree-branch"], { cwd: testDir });
965+
await execFileAsync(
966+
"git",
967+
["worktree", "add", linkedWorktreeDir, "feature/worktree-branch"],
968+
{
969+
cwd: testDir,
970+
}
971+
);
972+
973+
const result = await runGitCheckout(testDir, "feature/worktree-branch");
974+
975+
expect(result.success).toBe(false);
976+
expect(result.message).toContain("already used by worktree");
977+
expect(result.message).toContain(linkedWorktreeDir);
978+
} finally {
979+
await rm(linkedWorktreeDir, { recursive: true, force: true });
980+
}
981+
});
956982
});
957983

958984
describe("runGitPush", () => {

packages/server/src/git/cli.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,10 @@ export async function runGitCheckout(
551551
}
552552
): Promise<{ success: boolean; message: string; branch?: string }> {
553553
const args = ["checkout"];
554+
const formatCheckoutError = (error: unknown, fallbackMessage: string) =>
555+
error instanceof GitError
556+
? error.stderr.trim() || error.message || fallbackMessage
557+
: fallbackMessage;
554558

555559
// Detect remote branch refs by querying actual configured remotes
556560
let isRemoteRef = false;
@@ -584,10 +588,10 @@ export async function runGitCheckout(
584588

585589
// For remote branch checkout, we know the branch name from the ref
586590
return { success: true, message, branch: branchName };
587-
} catch {
591+
} catch (error) {
588592
return {
589593
success: false,
590-
message: `Failed to checkout remote branch '${ref}'`,
594+
message: formatCheckoutError(error, `Failed to checkout remote branch '${ref}'`),
591595
};
592596
}
593597
} else {
@@ -607,10 +611,10 @@ export async function runGitCheckout(
607611
const message = stdout || stderr || `Checkout to ${ref} completed`;
608612

609613
return { success: true, message, branch };
610-
} catch {
614+
} catch (error) {
611615
return {
612616
success: false,
613-
message: `Failed to checkout '${ref}'`,
617+
message: formatCheckoutError(error, `Failed to checkout '${ref}'`),
614618
};
615619
}
616620
}

0 commit comments

Comments
 (0)