repo: Add exclusive mode (park/restore/exclusive)#1304
Open
ed-irl wants to merge 3 commits into
Open
Conversation
Collaborator
Author
|
This change is part of the following stack: Change managed by git-spice. |
This was referenced Jun 23, 2026
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).
82a6c21 to
6814dc5
Compare
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.
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 parkrecords 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 restorere-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 PATHdiscards 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 createis refused to avoid racing the parking process. Each parked commit is pinned underrefs/gs-park/so it survives GC until the worktree is recovered.State gains
Park/Unpark/InExclusiveMode/ParkedWorktreesbacked by an additive, optionalexclusivestore key, and git gainsDeleteRef. 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.