swarmops ref delete#
Delete ref NAME.
- Group
refs- Since
0.1.0- Mutates
- yes
- Identity required
- yes
- MCP tool
ref_delete- Envelope op
ref_delete- Exit codes
- 045
Syntax#
swarmops ref delete [OPTIONS] --expect <REV> <NAME>Required arguments#
Syntax: <NAME>.
The ref.
Syntax: --expect <REV>.
The changeset the ref holds now.
Give the full changeset id you read (from ref list, show, log or a commit's result). A ref name or a relative revision such as main~1 is read from the store when the command runs instead of pinning the id you read: the ref's own name always matches (a deleted ref errors instead), so the compare-and-swap protects nothing, and main~1 on main never matches. An id prefix pins the id you read only until another changeset shares it; then it is E_AMBIGUOUS_ID.
After E_CAS_MISMATCH, the ref holds the error's actual, which someone else moved it to: look at it (swarmops show <actual>) before you delete it with --expect <actual>.
Optional arguments#
The command also takes the global options.
Examples#
swarmops --repo [tmp]/store --as agent/worker-17 ref delete release/1.0 --expect [c1]{
"ok": true,
"op": "ref_delete",
"api": 1,
"result": {
"name": "release/1.0",
"old": "[c1]",
"already_applied": false
},
"meta": {
"repo": "[tmp]/store",
"elapsed_ms": "[elapsed_ms]",
"resolved": {
"[c1]": "[c1]"
},
"auth": "trust"
}
}Exit code 0. Recorded by the CLI tests. A name in square brackets, such as [tmp] or [c1], stands for what differs from run to run: the test's temporary directory, an id, a time.
No recorded example yet.
Details#
ref delete removes one ref by compare-and-swap: it deletes the ref only if it still names the
changeset you give as --expect. Deleting a ref removes the name only. Every changeset stays in
the store, readable by id, and op undo of the deletion creates the ref again.
What happens, in order#
- Identity. Without
--asorSWARMOPS_AGENTthe command fails withE_IDENTITY_REQUIRED(exit 5) before it opens the store. - The expected target.
--expectis resolved as a revision first. A revision that names nothing isE_REV_NOT_FOUND(exit 6): so--expect release/1.0on a ref that is gone fails here, before the delete is tried. - The name.
NAMEmust bemainorrelease/<x>(letters, digits,.,_,-, not starting with., at most 255 bytes); anything else isE_REF_NAME_INVALID(exit 1). - The compare-and-swap, under the store's write lock, against the ref as committed:
| The ref holds | Result |
|---|---|
| The expected changeset | Deleted; old is that changeset, already_applied: false |
| Nothing (no such ref) | Replay: already_applied: true, nothing written |
| Another changeset | E_CAS_MISMATCH (exit 4), details.actual is what it holds |
A ref that does not exist counts as deleted already, whoever deleted it, so a retry of a delete
that succeeded is safe. This holds for a name that never existed too: ref delete release/typo --expect <id> succeeds with already_applied: true as long as <id> is a changeset in the
store. Read already_applied when it matters whether this run deleted the ref.
On E_CAS_MISMATCH, someone moved the ref after you read it. The hint, swarmops show <actual>, only reads: look at what the ref holds now before you delete it with
--expect <actual>.
Deleting main#
main can be deleted like any ref. Afterwards log without a revision, and every command given
main (ls main, cat main:…), fails with E_REV_NOT_FOUND (exit 6, hint swarmops ref list),
and a commit without --parent records a changeset with no parent, the root of a new history. To
bring main back, op undo the deletion, or ref set main <id> --create.
After the delete#
The journal records the deletion as a ref move with no new target, with the agent's identity
and the time; op log lists it as a ref_move whose move has old and no new. A ref created
again under the same name starts at version 1. Durability, warnings, meta.recovered and the
10 s lock wait (E_BUSY) work as for ref set.
Patterns#
Delete a ref you just read:
OLD=$(swarmops resolve release/1.0 | jq -r '.result.id')
swarmops ref delete release/1.0 --expect "$OLD"Take a branch imported from git into its own ref, land it on main, then delete the ref:
One writer per trunk
runs this sequence.
Undo a deletion: find the newest operation that deleted the ref (a move with no new) and undo
it. op log lists 50 operations unless -n says otherwise; page with --before for older ones.
OP=$(swarmops op log | jq -r '[.result.ops[] | select(any(.ref_moves[]; .name == "main" and .new == null))][0].op')
swarmops op undo "$OP"Caveats#
- Expect a full id. A ref name or a relative revision as
--expectis read when the command runs:--expect release/1.0always matches the ref it deletes, so the compare-and-swap protects nothing. An id prefix pins the id only while no other changeset shares it. - No cleanup. Deleting a ref frees no space: the changesets it named, and their objects, stay.
Through MCP#
The MCP tool is ref_delete, with name and expected_old. The server refuses an
expected_old that is not a full 64-hex changeset id with E_INVALID_ARG (hint
swarmops ref list).
Guides#
- Commit and land: Move a ref yourself
- Reading and repairing history: Undo a ref's deletion
- Concepts: Ref
Return information#
result is a RefSetResp (swarmops schema RefSetResp prints its JSON Schema).
| Field | Type | Required | Description |
|---|---|---|---|
already_applied | boolean | yes | The ref was already in the requested state, so nothing changed and a replay is safe; old and new are then the request's expected_old and new, resolved to full ids. |
name | string | yes | The ref. |
new | string or null | no | Its target after; omitted when the ref was deleted. |
old | string or null | no | What the ref held before a move that was applied. On a replay (already_applied) it is expected_old as resolved, which the ref need not have held; omitted when create was given. |
warnings | array of string | no | Problems found after the move became durable, such as failed housekeeping; the move itself succeeded. Omitted when empty. |
Envelope op: ref_delete.
Exit codes:
0: Success.4: The operation can succeed when it is run again.5: An identity or policy requirement refused the operation.
Errors#
- E_IDENTITY_REQUIRED (exit 5): A mutation was asked for without an identity.
- E_CAS_MISMATCH (exit 4): The ref no longer holds the expected target (or, with
create, exists at another one);details.actualholds what it does,nullwhen the ref does not exist.
Any command that opens a store may also fail with a store error, such as E_NOT_A_REPO, E_IO or E_STORE_CORRUPT; a command line the grammar refuses is E_INVALID_ARG (exit 2).