Page kind: Reference
revert#
Takes back changeset (with since, the first-parent range after since) on target, main by default, by landing its inverse: what the target gained since stays, and a later change to the same lines is E_CONFLICT naming the changeset that made it, nothing recorded. Give a reason; the landed changeset records it and the range (show's reverts and revert_reason). Give idempotency_key to make a retry safe, and expect_target as a full 64-hex id.
- Since
0.11.0- Mutates
- yes
- Identity required
- yes
- Envelope op
revert- Cli command
swarmops revert- Request type
RevertReq- Annotations
{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":false}- Max result chars
null- CLI command
swarmops revert
Input schema#
arguments is a RevertReq: swarmops schema RevertReq prints the type. A field the type does not know is ignored.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
changeset | string | yes | The range's last changeset: on the target's first-parent chain (else E_INVALID_ARG, details.reason not_on_target). A revision as the caller wrote it, for the store to resolve: a ref name (main, release/1.2), a full 64-hex changeset id or a unique prefix of at least 12 hex digits, or a ref's earlier value: <ref>@{N} the value it held N moves before its current one (@{0} is the current value), <ref>@{at=<unix seconds>} the value set by its newest move recorded at or before that instant (the writer's clock, moves read in journal order); optionally followed by ~N for the N-th first-parent ancestor. | |
expect_target | string or null | no | Publish only while the target names this changeset, as a land's. | |
idempotency_key | string or null | no | Makes a retry safe, as a land's key: the same revert again replays it; the same key for another range is E_INVALID_ARG. | |
max_attempts | integer | no | 8 | How many times to try to publish before failing with E_CAS_RETRY_EXHAUSTED: 1 to 32. |
max_conflict_bytes | integer | no | 32768 | The most bytes of hunk text an E_CONFLICT report carries, as a land's. |
message | string or null | no | The landed changeset's message. When omitted, Revert <12 hex digits of changeset>: <its title> (a range: Revert <n> changesets <since>..<changeset>), a blank line and the reason. | |
reason | string | yes | Why: 1 to 4,096 bytes, recorded as the landed changeset's revert_reason metadata, and the default message's body. | |
since | string or null | no | Where the range starts, exclusive: a first-parent ancestor of changeset. When omitted, its first parent, so the range is changeset alone; a root's is the empty tree. At most 256 changesets (E_TOO_LARGE). | |
target | string | no | "main" | The ref to land the revert on: main or release/<name>, which must exist. |
JSON Schema#
As tools/list gives it: each $ref replaced by its definition, so that it stands alone.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "`revert` (CLI `revert`): takes back the first-parent range `(since, changeset]` of `target`\nby a land. The land commits the inverse change on `changeset`, every path the range touched\nset to what `since` held there, and lands it from `changeset`: what\nthe target gained since stays, a later change to the same lines is `E_CONFLICT` naming the\nchangeset that made it, and nothing is recorded then. A range whose changes cancel out, or\none the target took back already, is `E_NOTHING_TO_LAND`. A range whose changesets include\nmerges is taken back against their first parents.",
"properties": {
"changeset": {
"description": "The range's last changeset: on the target's first-parent chain (else `E_INVALID_ARG`,\n`details.reason` `not_on_target`). A revision as the caller wrote it, for the store to resolve: a ref name (`main`,\n`release/1.2`), a full 64-hex changeset id or a unique prefix of at least 12 hex digits, or a\nref's earlier value: `<ref>@{N}` the value it held N moves before its current one (`@{0}`\nis the current value), `<ref>@{at=<unix seconds>}` the value set by its newest move\nrecorded at or before that instant (the writer's clock, moves read in journal order);\noptionally followed by `~N` for the N-th first-parent ancestor.",
"type": "string"
},
"expect_target": {
"anyOf": [
{
"pattern": "^[0-9a-fA-F]{64}$",
"type": "string"
},
{
"type": "null"
}
],
"description": "Publish only while the target names this changeset, as a land's."
},
"idempotency_key": {
"description": "Makes a retry safe, as a land's key: the same revert again replays it; the same key for\nanother range is `E_INVALID_ARG`.",
"type": [
"string",
"null"
]
},
"max_attempts": {
"default": 8,
"description": "How many times to try to publish before failing with `E_CAS_RETRY_EXHAUSTED`: 1 to 32.",
"format": "uint32",
"maximum": 32,
"minimum": 1,
"type": "integer"
},
"max_conflict_bytes": {
"default": 32768,
"description": "The most bytes of hunk text an `E_CONFLICT` report carries, as a land's.",
"format": "uint64",
"minimum": 0,
"type": "integer"
},
"message": {
"description": "The landed changeset's message. When omitted, `Revert <12 hex digits of changeset>:\n<its title>` (a range: `Revert <n> changesets <since>..<changeset>`), a blank line and\nthe reason.",
"type": [
"string",
"null"
]
},
"reason": {
"description": "Why: 1 to 4,096 bytes, recorded as the landed changeset's `revert_reason` metadata, and\nthe default message's body.",
"type": "string"
},
"since": {
"anyOf": [
{
"description": "A revision as the caller wrote it, for the store to resolve: a ref name (`main`,\n`release/1.2`), a full 64-hex changeset id or a unique prefix of at least 12 hex digits, or a\nref's earlier value: `<ref>@{N}` the value it held N moves before its current one (`@{0}`\nis the current value), `<ref>@{at=<unix seconds>}` the value set by its newest move\nrecorded at or before that instant (the writer's clock, moves read in journal order);\noptionally followed by `~N` for the N-th first-parent ancestor.",
"type": "string"
},
{
"type": "null"
}
],
"description": "Where the range starts, exclusive: a first-parent ancestor of `changeset`. When omitted,\nits first parent, so the range is `changeset` alone; a root's is the empty tree. At most\n256 changesets (`E_TOO_LARGE`)."
},
"target": {
"default": "main",
"description": "The ref to land the revert on: `main` or `release/<name>`, which must exist.",
"type": "string"
}
},
"required": [
"changeset",
"reason"
],
"title": "RevertReq",
"type": "object"
}Annotations#
It adds a changeset onto a ref's head and moves the ref to it, keeping all the ref held. Run again with the same arguments, it finds its change on the ref and adds nothing: replayed with an idempotency_key, E_NOTHING_TO_LAND without.
| Annotation | Value | Meaning |
|---|---|---|
destructiveHint | false | True: a tool that changes the store may overwrite or delete what is there, not only add to it. |
idempotentHint | true | True: calling it again with the same arguments changes nothing more. |
openWorldHint | false | True: it reaches beyond a closed set of things. Every tool here stays inside the store. |
readOnlyHint | false | True: the tool does not change its environment, the store. |
Its entry in tools/list carries no _meta.
CLI command#
swarmops revert runs the same operation and prints the same envelope.
Examples#
{
"id": 41,
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"arguments": {
"changeset": "[theirs]",
"idempotency_key": "revert-1",
"reason": "the docs were wrong"
},
"name": "revert"
}
}{
"id": 41,
"jsonrpc": "2.0",
"result": {
"content": [
{
"text": "{\"api\":1,\"meta\":{\"auth\":\"trust\",\"elapsed_ms\":\"[elapsed_ms]\",\"repo\":\"[tmp]/store\",\"resolved\":{\"[theirs]\":\"[theirs]\",\"main\":\"[id15]\"}},\"ok\":true,\"op\":\"revert\",\"result\":{\"land\":{\"attempts\":1,\"base\":\"[theirs]\",\"files_changed\":1,\"landed\":\"[reverted]\",\"rebased_onto\":\"[id15]\",\"relocated\":false,\"squashed_from\":[\"[id16]\"],\"status\":\"landed\",\"target\":\"main\"},\"reverted\":[\"[theirs]\"]}}",
"type": "text"
}
],
"isError": false,
"structuredContent": {
"api": 1,
"meta": {
"auth": "trust",
"elapsed_ms": "[elapsed_ms]",
"repo": "[tmp]/store",
"resolved": {
"[theirs]": "[theirs]",
"main": "[id15]"
}
},
"ok": true,
"op": "revert",
"result": {
"land": {
"attempts": 1,
"base": "[theirs]",
"files_changed": 1,
"landed": "[reverted]",
"rebased_onto": "[id15]",
"relocated": false,
"squashed_from": [
"[id16]"
],
"status": "landed",
"target": "main"
},
"reverted": [
"[theirs]"
]
}
}
}
}The server ran as swarmops mcp --repo [tmp]/store --as agent/worker-17, after initialize. Recorded by the MCP 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, the version.
Return information#
A tool result: the envelope, whose op is revert, as structuredContent and again as the text of its one content block. isError is true exactly when the envelope's ok is false. On success the envelope's result is what swarmops revert returns.
Errors#
A failed call is a tool result with isError: true; the envelope's error.code is one of the error codes.
- E_INVALID_ARG: arguments that do not fit
RevertReq, a field named twice among them included, or that break one of the server's own rules. - E_IDENTITY_REQUIRED: the server runs with no identity.
- E_NOT_A_REPO: the server's store is not there; the server serves on.
- E_INTERNAL: the operation panicked, a bug.
Then the errors of the operation, as swarmops revert lists them.
See also#
resolve_rev
The full id of the changeset a revision names (a ref name, a full id or a unique prefix of 12 or more hex digits, then any \~N suffixes), resolved as every…
show
One changeset in full: its parents, author, message, changes and signatures; pass max\_changes of 100 or less, since clients limit long tool results.