Merge pull request #758 from jeremymcs/fix/757-worktree-merge-checkout

fix: skip redundant checkout in worktree merge when main already current
This commit is contained in:
TÂCHES 2026-03-16 20:02:06 -06:00 committed by GitHub
commit 30dad00965
2 changed files with 40 additions and 2 deletions

View file

@ -429,8 +429,12 @@ export function mergeMilestoneToMain(
const integrationBranch = readIntegrationBranch(originalBasePath_, milestoneId);
const mainBranch = integrationBranch ?? prefs.main_branch ?? "main";
// 5. Checkout integration branch
nativeCheckoutBranch(originalBasePath_, mainBranch);
// 5. Checkout integration branch (skip if already current — avoids git error
// when main is already checked out in the project-root worktree, #757)
const currentBranchAtBase = nativeGetCurrentBranch(originalBasePath_);
if (currentBranchAtBase !== mainBranch) {
nativeCheckoutBranch(originalBasePath_, mainBranch);
}
// 6. Build rich commit message
const milestoneTitle = roadmap.title.replace(/^M\d+:\s*/, "").trim() || milestoneId;

View file

@ -290,6 +290,40 @@ async function main(): Promise<void> {
assertTrue(existsSync(join(repo, "feature.ts")), "feature.ts merged to main");
}
// ─── Test 6: Skip checkout when main already current (#757) ───────
console.log("\n=== skip checkout when main already current (#757) ===");
{
const repo = freshRepo();
const wtPath = createAutoWorktree(repo, "M060");
addSliceToMilestone(repo, wtPath, "M060", "S01", "Skip checkout test", [
{ file: "skip-checkout.ts", content: "export const skip = true;\n", message: "add skip-checkout" },
]);
const roadmap = makeRoadmap("M060", "Skip checkout verification", [
{ id: "S01", title: "Skip checkout test" },
]);
// Verify main is already checked out at repo root (worktree default)
const branchAtRoot = run("git rev-parse --abbrev-ref HEAD", repo);
assertEq(branchAtRoot, "main", "main is already checked out at project root");
// mergeMilestoneToMain should succeed without attempting to checkout main
// (which would fail with "already used by worktree" error)
let threw = false;
try {
const result = mergeMilestoneToMain(repo, "M060", roadmap);
assertTrue(result.commitMessage.includes("feat(M060)"), "merge commit created");
} catch (err) {
threw = true;
console.error("Unexpected error:", err);
}
assertTrue(!threw, "does not fail when main is already checked out at project root");
// Verify the merge actually happened
assertTrue(existsSync(join(repo, "skip-checkout.ts")), "skip-checkout.ts merged to main");
}
} finally {
process.chdir(savedCwd);
for (const d of tempDirs) {