The README rules a shared remote out of scope. The honest design: the store is a bare repo with a remote; claim = fetch refs/locks/*, plan locally, run the transaction locally, then push --atomic --force-with-lease of exactly the touched refs; a rejected push means someone else moved a ref and the claim re-reads and retries (same shape as the semaphore generation loop). Latency is a round trip per claim; correctness holds because push is atomic per ref set and force-with-lease is the compare-and-swap. Worth a spike before deciding; would make git-locks the lock service for a team without running a service.
The README rules a shared remote out of scope. The honest design: the store is a bare repo with a remote;
claim=fetch refs/locks/*, plan locally, run the transaction locally, thenpush --atomic --force-with-leaseof exactly the touched refs; a rejected push means someone else moved a ref and the claim re-reads and retries (same shape as the semaphore generation loop). Latency is a round trip per claim; correctness holds because push is atomic per ref set and force-with-lease is the compare-and-swap. Worth a spike before deciding; would make git-locks the lock service for a team without running a service.