From f2286b7c6af94da457f31ee021b76934245b21c0 Mon Sep 17 00:00:00 2001 From: Charlie Date: Fri, 17 Apr 2026 10:18:07 +1000 Subject: [PATCH] fix: gstack-upgrade uses ff-only merge before the hard reset The upgrade flow uses `git reset --hard origin/main` to advance HEAD. This trips destructive-command blockers (Claude Code PreToolUse hooks, pre-commit wrappers, /careful, /guard) and can abort auto-upgrades mid-flow. Switch to `git merge --ff-only origin/main` as the primary path. Falls back to the old behavior if fast-forward fails (divergent history, local commits). Clean global installs never hit the destructive flag. Also switches `git stash` to `git stash push --include-untracked -m "pre-upgrade-"` so untracked build artifacts (.bak/, compiled binaries) don't block the merge, and the stash is self-describing. Tested on Windows 11 with a Claude Code PreToolUse guard that blocks destructive git operations. Upgraded from v0.16.2.0 to v0.18.1.0 cleanly via the ff-only path, setup regenerated customizations as expected. --- gstack-upgrade/SKILL.md.tmpl | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/gstack-upgrade/SKILL.md.tmpl b/gstack-upgrade/SKILL.md.tmpl index 5402a1da3..531d5b44a 100644 --- a/gstack-upgrade/SKILL.md.tmpl +++ b/gstack-upgrade/SKILL.md.tmpl @@ -125,9 +125,16 @@ Use the install type and directory detected in Step 2: **For git installs** (global-git, local-git): ```bash cd "$INSTALL_DIR" -STASH_OUTPUT=$(git stash 2>&1) +STASH_OUTPUT=$(git stash push --include-untracked -m "pre-upgrade-$(date +%Y-%m-%d)" 2>&1) git fetch origin -git reset --hard origin/main +# Try fast-forward first. Safer than reset --hard and passes through guard +# hooks (Claude Code PreToolUse, pre-commit wrappers) that block destructive +# ops. Falls back to reset for divergent history — no-op when the working +# tree is clean and there are no local commits, which is the expected state +# for a global install. +if ! git merge --ff-only origin/main 2>/dev/null; then + git reset --hard origin/main +fi ./setup ``` If `$STASH_OUTPUT` contains "Saved working directory", warn the user: "Note: local changes were stashed. Run `git stash pop` in the skill directory to restore them."