Skip to content

Commit 044def4

Browse files
committed
Enable cross-worktree rebase and sync
1 parent 4c1661f commit 044def4

19 files changed

Lines changed: 1099 additions & 884 deletions

File tree

‎.github/copilot-instructions.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ No Makefile, no code generation, no external linter config. Standard Go toolchai
3737
- Load stack files with `stack.Load(dir)` after writing to get correct checksums.
3838
- Use `stackStateDir(cfg)` for application state and `beginStackMutation` before mutation snapshots; defer cleanup. The clone-wide operation lock is separate from short catalog saves.
3939
- Recovery must match stack identity, execute in the recorded worktree, and retain journals on partial failures. Native Git markers stay per-worktree.
40-
- Mutation locks coordinate gh-stack only, not Git commands/editors. Keep affected worktrees quiescent during rewrites. Context-tracked modify passes the snapshot SHA (or prior `Context.Touched` SHA) to `Context.Start`; never claim an external commit as this operation's work during continuation.
41-
- Rebase/sync currently reject foreign-owned members and writable trunks after prerequisite migration but before requested mutations, including sync reconciliation. Their existing engine remains origin-only; rebase recovery must be invoked in its recorded origin.
40+
- Finish paused operations before switching preview stages or versions. Reject origin-only and unknown rebase execution modes before routing recovery; use the matching layer3 build in the recorded origin for origin-only journals.
41+
- Mutation locks coordinate gh-stack only, not Git commands/editors. Keep affected worktrees quiescent during rewrites. Pass the snapshot SHA (or prior `Context.Touched` SHA) to `Context.Start` before ref mutations; never claim an external commit as this operation's work during continuation.
4242
- Core modify rejects distributed stack branches before TUI/apply; foreign trunk ownership alone is allowed. Do not enable distributed modify until its dependent layer is implemented.
4343

4444
For full architecture details, see [AGENTS.md](../AGENTS.md) in the repository root.

‎AGENTS.md‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,11 @@ if errors.As(err, &exitErr) { ... }
123123
- **Locking:** `<common-dir>/gh-stack.lock` protects short catalog saves; `<common-dir>/gh-stack-operation.lock` serializes clone-wide mutations. Acquire `beginStackMutation` before snapshots/preflight and defer its cleanup. Never hold a catalog lock across Git operations or call lock-taking `stack.Save` while already holding that lock. Errors surface as `LockError`.
124124
- **Staleness:** Concurrent modifications detected via `StaleError`.
125125
- **Migration:** Consolidate only nonconflicting legacy catalogs and preserve originals. Stop on conflicting definitions; finish legacy recovery in its original worktree before migrating. Do not mix old and new writers.
126-
- **Recovery:** gh-stack journals live in the common directory and record the origin, stack identity, original refs, and progress. Native Git markers remain per-worktree. Rebase continue/abort currently requires the recorded original worktree; modify uses a scoped origin executor even when invoked elsewhere. Match stack identity (not catalog array position) and retain state on any partial restore or save failure.
127-
- **External changes:** Mutation locks coordinate gh-stack, not arbitrary Git commands or editors. Keep affected worktrees quiescent during rewrites, except for requested conflict resolution while paused. Context-tracked modify calls `Context.Start(branch, expectedSHA)` before ref mutations, using the snapshot or last `Context.Touched` SHA. Do not adopt a freshly read tip as the operation's baseline during continuation.
126+
- **Recovery:** gh-stack journals live in the common directory and record origin/owner identities, original refs, and progress. Native Git markers remain per-worktree. Continue/abort must use recorded scoped executors, match stack identity (not catalog array position), and retain state on any partial restore or save failure.
127+
- **External changes:** Mutation locks coordinate gh-stack, not arbitrary Git commands or editors. Keep affected worktrees quiescent during rewrites, except for requested conflict resolution while paused. Call `Context.Start(branch, expectedSHA)` before ref mutations: use the original snapshot SHA, or the last `Context.Touched` SHA for a branch already changed by this operation. Do not adopt a freshly read tip as this operation's baseline during continuation.
128128
- **Separate Git directories:** Native topology may report the administration directory as the main worktree path for `--separate-git-dir` repositories. A known origin remains usable, but a foreign main-owner root may be undiscoverable. Never infer a working directory from an administration path, emit it as a successful navigation target, or add a private registry/config mutation to guess ownership.
129129
- **Core modify boundary:** Plain modify permits unoccupied branches and branches owned by its origin worktree, but rejects distributed stack membership before the TUI/apply. Trunk ownership alone does not block it. Full distributed modify is a separate layer.
130-
- **Intermediate rebase/sync boundary:** Keep the existing origin-only execution engine. After prerequisite catalog migration, reject all foreign-owned member/rollback targets and any trunk that would be updated before requested mutations. Sync must check remote-added/replacement branches before importing or saving membership. Stack selection cannot eagerly checkout before this preflight. Multi-owner execution is deferred.
131-
- **Journal transition:** New rebase/sync journals carry `executionMode: "origin-only"`. Their context identifies the origin, not distributed per-step progress. Future engines must recognize this marker before routing recovery and either use compatible origin-bound recovery or fail closed with matching-build instructions. Never reinterpret it as a distributed journal; this build likewise rejects unmarked non-null contexts and unknown modes. Legacy null-context journals retain their original-catalog route.
130+
- **Journal transition:** Complete paused operations before switching preview stages or versions. Unmarked rebase/sync journals with a worktree context use distributed recovery. Reject `executionMode: "origin-only"` before context-based routing or mutation; preserve its bytes and require the matching layer3 build in the recorded origin. Unknown nonempty modes also fail closed. Empty-mode journals without a context retain the legacy original-catalog route.
132131

133132
## CI workflows (`.github/workflows/`)
134133

‎README.md‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,15 @@ Stack metadata is stored in `<common-dir>/gh-stack` (a JSON file, not committed
6464

6565
The gh-stack recovery journals, `gh-stack-rebase-state` and `gh-stack-modify-state`, also live in the common directory and record the worktrees involved. Git's own HEAD, index, rebase, and cherry-pick markers remain **per worktree**.
6666

67-
On upgrade, nonconflicting legacy worktree catalogs are consolidated automatically and originals are preserved as backups. Migration is a prerequisite and can complete even if the requested rewrite is subsequently refused. Conflicting definitions stop migration rather than choosing one; the error identifies the files to reconcile. Finish or abort legacy in-progress operations in their original worktree first. Do not mix old and new gh-stack versions within one clone.
67+
On upgrade, nonconflicting legacy worktree catalogs are consolidated automatically and originals are preserved as backups. Conflicting definitions stop migration rather than choosing one; the error identifies the files to reconcile. Finish or abort legacy in-progress operations in their original worktree first. Do not mix old and new gh-stack versions within one clone.
68+
69+
Complete paused operations before switching preview stages or gh-stack versions. If recovery reports an incompatible execution lifecycle, finish or abort it using the matching build in its recorded original worktree; do not edit or remove the journal.
6870

6971
### Git worktrees
7072

71-
You can keep independent stacks in linked worktrees or track a stack whose branches are distributed across them. **For now, `rebase` and `sync` require all stack branches to be unoccupied or checked out in the initiating worktree.** They conservatively refuse foreign-owned members, even outside a requested rebase range, before changing refs, checkouts, stack membership, or remote stacks. A foreign-owned trunk is also refused when trunk updates are enabled; `rebase --no-trunk` does not update it.
73+
You can keep independent stacks in linked worktrees or distribute a stack's branches across them. `rebase` and `sync` automatically update the clean worktree that owns each affected branch. Dirty, busy, missing, or changed owners stop the operation; unrelated worktrees are left alone. A trunk that cannot safely fast-forward can use the existing fetched-remote fallback.
7274

73-
Mutations are serialized across the clone, while read-only views remain available. Paused operations must be continued or aborted before another mutation. Rebase recovery must be invoked in its recorded original worktree; invoking it elsewhere fails without changing either checkout. Modify recovery can be invoked elsewhere and still executes in its recorded origin. gh-stack never automatically stashes changes, creates/removes worktrees, or steals another checkout.
75+
Mutations are serialized across the clone, while read-only views remain available. Paused operations must be continued or aborted before another mutation. Recovery runs in the recorded worktree even when `--continue` or `--abort` is invoked elsewhere. gh-stack never automatically stashes changes, creates/removes worktrees, or steals another checkout.
7476

7577
Mutation locks coordinate **gh-stack processes only**, not arbitrary Git commands, editors, or other tools. Keep affected worktrees idle while history is being rewritten. During a pause, make only the requested conflict-resolution edits and staging in the reported worktree.
7678

0 commit comments

Comments
 (0)