Skip to content

repo: Add exclusive mode (park/restore/exclusive)#1304

Open
ed-irl wants to merge 3 commits into
ed-irl/anchor-rmfrom
ed-irl/repo-exclusive
Open

repo: Add exclusive mode (park/restore/exclusive)#1304
ed-irl wants to merge 3 commits into
ed-irl/anchor-rmfrom
ed-irl/repo-exclusive

Conversation

@ed-irl

@ed-irl ed-irl commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Adds an exclusive mode that hands the whole repository to a single process so it can reorganize the stack without contending with worktrees owned by other processes.

New commands:

  • gs repo park records every linked worktree in a durable manifest (in spice state) and removes the worktree directories, leaving the branches intact and reachable from the primary checkout. Dirty worktrees are refused unless --force. The manifest is written before any removal, so an interrupted park resumes by re-running.
  • gs repo restore re-creates the parked worktrees at their branches' tips and clears the marker. It is idempotent and resumable. If a parked branch was deleted out-of-band, restore leaves the rest in place, stays in exclusive mode, and explains how to recover; --forget PATH discards a worktree whose branch is gone on purpose.
  • gs repo exclusive -- <cmd> wraps a command in park/restore, always restoring afterward even if the command fails.

While parked, gs anchor create is refused to avoid racing the parking process. Each parked commit is pinned under refs/gs-park/ so it survives GC until the worktree is recovered.

State gains Park/Unpark/InExclusiveMode/ParkedWorktrees backed by an additive, optional exclusive store key, and git gains DeleteRef. Covered by unit tests and test scripts for the round-trip, detached HEAD, dirty refusal, crash recovery, branch-gone wedge, forget, and the exclusive wrapper.

ed-irl added 2 commits June 23, 2026 13:48
Parallel processes (agents, CI, the human) share one git-spice
repository through worktrees. Restacks and syncs stay scoped to a
worktree's anchor, but some operations need the whole stack to
themselves. Exclusive mode is the writer lock for those.

'gs repo park' records every linked worktree in a durable manifest
(stored in the spice data ref, so it survives the worktree dirs being
removed) and then removes the directories, leaving the entire graph
reachable from the primary checkout. The manifest is written before any
removal, so an interrupted park is resumable. Dirty worktrees are
refused unless --force.

'gs repo restore' re-creates the parked worktrees at their branches'
current tips and clears the marker; it is idempotent and crash-resumable.

'gs repo exclusive -- <cmd>' parks, runs the command with the repo to
itself, and always restores afterward, even on failure.

While parked, 'gs anchor create' is refused: the repository belongs to
the parking process until restore.
…ked branch is deleted

Fixes from adversarial review (repo-exclusive layer):
- park records each worktree's HEAD; restore re-creates a detached
  worktree at that commit instead of the primary's HEAD, so a detached
  checkout's position is no longer lost (B3)
- park: document precisely what 'dirty' covers (staged, unstaged,
  untracked) and that repo-global stashes are never discarded (M5)

When the exclusive command deletes a parked branch out-of-band,
git-spice state is left inconsistent. Rather than fabricating a branch
at a possibly-stale commit or silently dropping the worktree, restore
now restores every other worktree, stays in exclusive mode, and reports
the missing branch with recovery steps. Recover by re-creating the
branch and re-running restore, or discard the worktree with
'gs repo restore --forget PATH'. Each parked commit is pinned under
refs/gs-park/ so it survives garbage collection until recovered (B4).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant