mirror of
https://github.com/github/gh-stack.git
synced 2026-09-14 20:26:28 +08:00
700d9cfc94
`gh stack sync` and `gh stack rebase` could print a full success report while leaving the stack based on the trunk it was created from. Two independent causes. 1. A rebase git refused was reported as a success. `tryAutoResolveRebase` returned nil whenever no rebase was in progress. That is only a valid success signal after an auto-`--continue`; on the first check it means `git rebase` exited non-zero without ever starting. Every rebase funnels through it, so the cascade printed `✓ Rebased X onto Y` for a rebase that never ran — a dirty tree, a branch checked out in another worktree, an unresolvable upstream, or stale rebase state. A rebase that never started is now a typed `*git.RebaseStartError`, which the cascade and `modify` treat as fatal rather than as a conflict, so no bogus recovery state is written and git's own message is surfaced. 2. The trunk ref was never verified against the remote. `fastForwardTrunk` only warned when it could not move the local trunk (checked out in another worktree, diverged, remote ref gone), and the cascade then rebased onto the stale local trunk. Every freshness check compared branches to the *local* trunk, so they all passed: `rebase` claimed "rebased locally with main" and `sync` concluded nothing was stale, force-pushed anyway, and said "Branches synced". `resolveTrunkTarget` now resolves the ref the cascade must target. When the local trunk cannot be updated it returns `<remote>/<trunk>` and says why, so the stack ends up current regardless of why the local ref is stuck. When the trunk no longer exists on the remote it fails with an actionable message instead of silently rebasing onto a stale trunk. The post-cascade check measures against that ref, and `sync` runs it before pushing so an unrebased stack is never force-pushed. Also fixed along the way: - A remote-qualified trunk (`gh stack init --base origin/main`) is normalized instead of being re-qualified into `origin/origin/main`, in both commands and before fetch refspecs are built. - `git rebase <option> --continue` is a usage error (exit 129), so `--preserve-dates` broke every `--continue`. git persists the option in the rebase state, so `--continue` alone honors it. - `FetchBranches` reports real failures instead of `sync` printing "Fetched latest changes" regardless. - Preflight checks for a rebase in progress and a dirty tree, with `--autostash` to opt out. Untracked files are not treated as dirty: git rebases fine with them present. `--autostash` stashes once around the whole cascade — git's own `--autostash` pops after every individual rebase, landing the changes on the wrong branch. - Both summaries now name the trunk ref and SHA the stack landed on. Fixes #155, #176. Addresses discussion #215. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f5959297-80fd-4732-aeae-aa9a4b6a7755