Repository navigation
Use gh stack's shared catalog instead of per worktree files - #66
Merged
Merged
Conversation
gh-stack 0.3 keeps one stack catalog in the common git dir for every worktree, and on its first run moves each worktree's own file into it, keeping a backup. git-stack still read and wrote the per worktree files, so after that move it put the stack back into the worktree's file (to "adopt" it), gh stack tried to move it again, found its backup no longer matched and refused every command from then on: cannot migrate stack catalogs: existing backup differs from the original catalog Read and write only <common-dir>/gh-stack now, and drop adopt, since gh stack finds every stack from every worktree there. A per worktree file left over from 0.2 is merged in by the next write, snapshot or gh stack call, under both of gh stack's locks, the shared file winning over the current worktree's and that over the others, and is then moved aside to .pre-worktree-migration (or .1, .2 when gh stack's own backup is in the way), so a stale backup never blocks it. While gh stack's own move is part way through, or a worktree has an interrupted gh stack rebase or modify, it is left alone with a state_migration error saying why. Load still reads the old files, without writing, so nothing disappears before the move. Preflight now wants gh-stack v0.3.0 or later, and gh stack's own migration error maps to state_migration too. Stack.Worktree goes, since a stack no longer belongs to a worktree.
There was a problem hiding this comment.
🟡 Changes recommended
Critical migration and snapshot/restore defects can lose stack tracking or block recovery, and migration checks fail to detect interrupted main-checkout operations.
5 open issues
What changed in this PR
Updates git-stack to use gh-stack 0.3’s shared repository catalog, replacing per-worktree storage and removing the adoption step that caused migration conflicts.
Changes:
- Consolidates legacy catalogs into shared storage, with backup handling and migration safeguards.
- Requires gh-stack v0.3.0 or later and introduces the
state_migrationerror code. - Updates snapshots, recovery handling, tests, and documentation for shared storage.
| File | Description |
|---|---|
| README.md | Documents the minimum extension version and shared stacks. |
| pkg/stack/ports.go | Removes per-worktree placement from the metadata contract. |
| pkg/stack/model.go | Removes stack worktree ownership. |
| pkg/stack/errors.go | Adds the migration error kind and code. |
| pkg/backend/ghstack/worktrees_test.go | Tests shared-first catalog loading. |
| pkg/backend/ghstack/update_test.go | Tests shared writes, migration, backups, and safeguards. |
| pkg/backend/ghstack/tracker.go | Removes adoption before adding branches. |
| pkg/backend/ghstack/submitter.go | Removes adoption and migrates before terminal execution. |
| pkg/backend/ghstack/stream_test.go | Updates extension-version fixtures. |
| pkg/backend/ghstack/reshape_abort_test.go | Removes worktree ownership from snapshot fixtures. |
| pkg/backend/ghstack/preflight.go | Checks the minimum gh-stack version. |
| pkg/backend/ghstack/ghstack_test.go | Tests version checks and migration error mapping. |
| pkg/backend/ghstack/file.go | Updates package documentation for shared storage. |
| pkg/backend/ghstack/errors.go | Maps upstream migration failures to actionable errors. |
| pkg/backend/ghstack/backend.go | Implements shared catalogs, migration, locking, and snapshots. |
| pkg/backend/ghstack/backend_test.go | Tests shared snapshots and legacy restore compatibility. |
| pkg/app/sync_test.go | Updates sync fixtures for the simplified stack model. |
| pkg/app/sync_restack_test.go | Removes worktree ownership from restack fixtures. |
| pkg/app/sync_cleanup_test.go | Removes worktree ownership from cleanup fixtures. |
| pkg/app/restack_state.go | Detects recovery records in common and worktree directories. |
| pkg/app/reshape.go | Removes worktree ownership from reshape snapshots. |
| pkg/app/reshape_internal_test.go | Updates reshape restoration assertions. |
| docs/mcp.md | Documents the new migration error code. |
| docs/architecture.md | Explains shared storage and migration behavior. |
| AGENTS.md | Updates catalog-writing guidance. |
Review effort: Balanced
Comment on lines
+184
to
187
| for _, n := range names { | ||
| if seen[n] { | ||
| continue next | ||
| } |
Comment on lines
+345
to
+346
| for _, path := range legacy { | ||
| dir := filepath.Dir(path) |
| if err != nil { | ||
| return stack.Snapshot{}, err | ||
| } | ||
| defer unlock() |
| if err != nil { | ||
| return err | ||
| } | ||
| defer unlock() |
| } | ||
| if reMigration.MatchString(stderr) { | ||
| return stack.New(stack.KindStateMigration, "gh stack could not move the stacks kept per worktree into its shared file"). | ||
| WithSteps("run `git stack doctor --fix` to move them", "then run the command again"). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


gh-stack 0.3 quietly changed how it stores stacks (it's not in the release notes, it came in with their PR #528). Rather than one file in each worktree's git dir, it now keeps a single catalog in the common git dir that every worktree shares, and the first 0.3 command moves each worktree's file into it, keeping a
.pre-worktree-migrationbackup.git-stack still read and wrote the per worktree files, so the two fought: gh stack moved the stack into the shared file, git-stack's adopt step moved it straight back into the worktree's file (and added the next branch there), and on the next submit gh stack tried to move it again, found its backup no longer matched and refused every command from then on with
cannot migrate stack catalogs: existing backup differs from the original catalog.So git-stack now reads and writes only
<common-dir>/gh-stack, and adopt is gone since gh stack sees every stack from every worktree there. Any per worktree file left over is merged in by the next write, snapshot or gh stack call, under both of gh stack's locks, and then moved aside; when gh stack's own backup is already in the way it goes to.pre-worktree-migration.1(and on) instead of stopping, so a stuck repository like the one above sorts itself out. If gh stack is part way through its own move, or a worktree has an interrupted gh stack rebase or modify, the files are left alone with a newstate_migrationerror saying why.This needs gh-stack v0.3.0 or later now (preflight says so and how to upgrade), which is the one thing to do after upgrading git-stack.