From 2f459b5d03b345df8dc673326e05cebe4d03ffc9 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Tue, 17 Mar 2026 09:49:26 -0400 Subject: [PATCH] fix: remove untracked .gsd/ state files before milestone merge checkout (#827) (#834) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When merging a milestone back to main, `git checkout main` fails if untracked .gsd/ state files (STATE.md, completed-units.json, auto.lock) in the working tree conflict with tracked files on the branch. Remove these known GSD-managed state files before checkout. They are runtime artifacts regenerated by doctor/rebuildState and are not meaningful in the main working tree — the worktree had the real state. --- src/resources/extensions/gsd/auto-worktree.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/resources/extensions/gsd/auto-worktree.ts b/src/resources/extensions/gsd/auto-worktree.ts index c7081335e..874a9e699 100644 --- a/src/resources/extensions/gsd/auto-worktree.ts +++ b/src/resources/extensions/gsd/auto-worktree.ts @@ -6,7 +6,7 @@ * manages create, enter, detect, and teardown for auto-mode worktrees. */ -import { existsSync, cpSync, readFileSync, writeFileSync, readdirSync, mkdirSync, realpathSync, utimesSync } from "node:fs"; +import { existsSync, cpSync, readFileSync, writeFileSync, readdirSync, mkdirSync, realpathSync, utimesSync, unlinkSync } from "node:fs"; import { isAbsolute, join, resolve } from "node:path"; import { copyWorktreeDb, reconcileWorktreeDb, isDbAvailable } from "./gsd-db.js"; import { execSync, execFileSync } from "node:child_process"; @@ -560,6 +560,16 @@ export function mergeMilestoneToMain( // when main is already checked out in the project-root worktree, #757) const currentBranchAtBase = nativeGetCurrentBranch(originalBasePath_); if (currentBranchAtBase !== mainBranch) { + // Remove untracked .gsd/ state files that may conflict with the branch + // being checked out. These are regenerated by doctor/rebuildState and + // are not meaningful in the main working tree — the worktree had the + // real state. Without this, `git checkout main` fails with + // "Your local changes would be overwritten" (#827). + const gsdStateFiles = ["STATE.md", "completed-units.json", "auto.lock"]; + for (const f of gsdStateFiles) { + const p = join(originalBasePath_, ".gsd", f); + try { unlinkSync(p); } catch { /* non-fatal — file may not exist */ } + } nativeCheckoutBranch(originalBasePath_, mainBranch); }