# rebase

> Release: 0.11.0 · Last changed: 2026-11-08 · Source: https://github.com/KeiaiLab/SwarmOps/blob/stable/docs/reference/mcp-tools/rebase.md

Merges head (with its first-parent chain since base) three-way onto onto's head, main by default, as land merges it, and records the result as one changeset there without moving any ref: build and test that changeset, then land it with expect\_target set to result.onto, so that the landed tree is the one you tested. Pass head, base and resolutions' against as full 64-hex ids, and an idempotency\_key to make a retry safe.

```yaml
title: "rebase"
description: "Rebase a change."
since: "0.3.0"
mutates: true
identity_required: true
cli_command: "swarmops rebase"
envelope_op: "rebase"
request_type: "RebaseReq"
annotations: {"destructiveHint":false,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
max_result_chars: null
```

## Input schema

`arguments` is a `RebaseReq`: `swarmops schema RebaseReq` prints the type. A field the type does not know is ignored.

| Field | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `base` | string or null | no |  | Where the change starts, as a land's `base`: a first-parent ancestor of `head`; when omitted, the merge base of `head` and the head of `onto`. |
| `head` | string | yes |  | The changeset to rebase: the change's head. 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. |
| `idempotency_key` | string or null | no |  | Makes a retry safe: a uuid v7, as a commit's key. The same request on the same head of `onto` is the same changeset, replayed without writing. |
| `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 recorded changeset's message; `head`'s when omitted. |
| `onto` | string | no | `"main"` | The ref to rebase onto: `main` or `release/<name>`, which must exist. |
| `resolutions` | object or null | no |  | What to make of the paths a conflict report named, as a land's resolutions. |

### JSON Schema

As `tools/list` gives it: each `$ref` replaced by its definition, so that it stands alone.
Its descriptions' citations of the design documents are left out here.

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "description": "`rebase` (M5): merge a change three-way onto a ref's head and record the result as one\nchangeset whose parent is that head, moving no ref. The merge, its conflicts and its\nresolutions are a land's: a conflict is the error `E_CONFLICT`, with the\nreport in `details.report`, and nothing is recorded then.",
  "properties": {
    "base": {
      "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 change starts, as a land's `base`: a first-parent ancestor of `head`; when\nomitted, the merge base of `head` and the head of `onto`."
    },
    "head": {
      "description": "The changeset to rebase: the change's head. 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"
    },
    "idempotency_key": {
      "description": "Makes a retry safe: a uuid v7, as a commit's key. The same request on the same head of\n`onto` is the same changeset, replayed without writing.",
      "type": [
        "string",
        "null"
      ]
    },
    "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 recorded changeset's message; `head`'s when omitted.",
      "type": [
        "string",
        "null"
      ]
    },
    "onto": {
      "default": "main",
      "description": "The ref to rebase onto: `main` or `release/<name>`, which must exist.",
      "type": "string"
    },
    "resolutions": {
      "anyOf": [
        {
          "description": "A land's resolutions (`land --resolve`): what to make of some paths of the merge of the change\nonto the target, decided against one of the target's heads.",
          "properties": {
            "against": {
              "description": "The target's head the resolutions were decided against: the conflict report's `theirs`,\nby its full 64-hex id. A resolution applies while the target holds its path as this\nchangeset does (the same file, the same directory, or nothing). 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"
            },
            "files": {
              "additionalProperties": {
                "description": "What a land makes of one path, and of every path below it: exactly one of `take`, `content`\nand `delete` (anything else is `E_INVALID_ARG`, a rule the server checks), the rest of the\nmerge as it merged.",
                "properties": {
                  "content": {
                    "anyOf": [
                      {
                        "description": "A `put`'s content, as an object with one key.",
                        "oneOf": [
                          {
                            "additionalProperties": false,
                            "description": "UTF-8 text, verbatim.",
                            "properties": {
                              "inline": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "inline"
                            ],
                            "type": "object"
                          },
                          {
                            "additionalProperties": false,
                            "description": "Bytes in standard, padded base64.",
                            "properties": {
                              "base64": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "base64"
                            ],
                            "type": "object"
                          },
                          {
                            "additionalProperties": false,
                            "description": "A blob the store holds already, by its id (64 hex digits), as `blob_put` returns it: the\ncommit neither sends nor reads its bytes. An id the store holds no blob under (none, or\na tree's or a changeset's) is `E_INVALID_ARG`, and nothing is written. `blob_put` takes\nthe other forms only.",
                            "properties": {
                              "blob": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "blob"
                            ],
                            "type": "object"
                          },
                          {
                            "additionalProperties": false,
                            "description": "A file on the client's machine. The client reads it and sends its bytes, so the store is\nnever asked to read a path.",
                            "properties": {
                              "file": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "file"
                            ],
                            "type": "object"
                          }
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "One file of new content, given as a commit's change gives it (inline, base64, a client\nfile, or a stored blob by id), within a commit's limits; nothing below it."
                  },
                  "delete": {
                    "description": "Nothing there: no file at the path, nor below it.",
                    "type": "boolean"
                  },
                  "mode": {
                    "anyOf": [
                      {
                        "description": "The kind of entry a `put` writes.",
                        "oneOf": [
                          {
                            "const": "file",
                            "description": "A regular file (git mode 100644).",
                            "type": "string"
                          },
                          {
                            "const": "exec",
                            "description": "An executable file (git mode 100755).",
                            "type": "string"
                          },
                          {
                            "const": "symlink",
                            "description": "A symlink; the content is the link's target.",
                            "type": "string"
                          }
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "The kind of the file `content` makes, only beside it; when omitted, the kind of the file\nours holds there, else theirs', else a regular file."
                  },
                  "take": {
                    "anyOf": [
                      {
                        "description": "One side of a land's merge.",
                        "oneOf": [
                          {
                            "const": "ours",
                            "description": "The change: its head.",
                            "type": "string"
                          },
                          {
                            "const": "theirs",
                            "description": "The target: its head when the land merges.",
                            "type": "string"
                          }
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "What one side holds there: `ours`, the change's head, or `theirs`, the target's head."
                  }
                },
                "type": "object"
              },
              "description": "What to make of each path, by its repository path.",
              "type": "object"
            }
          },
          "required": [
            "against",
            "files"
          ],
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "description": "What to make of the paths a conflict report named, as a land's resolutions."
    }
  },
  "required": [
    "head"
  ],
  "title": "RebaseReq",
  "type": "object"
}
```

## Annotations

It adds to the store and changes nothing there. Run again, a `commit` adds again, another changeset signed at its own time, unless the call carries an `idempotency_key`, which makes the same call again a replay; a `blob_put` of the same content finds it stored, and says so in its result.

| 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` | `false` | 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 rebase`](../commands/rebase.md) runs the same operation and prints the same envelope.

## Examples

### MCP

```json
{
  "id": 12,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "head": "[head]"
    },
    "name": "rebase"
  }
}
```

```json
{
  "id": 12,
  "jsonrpc": "2.0",
  "result": {
    "content": [
      {
        "text": "{\"api\":1,\"meta\":{\"auth\":\"trust\",\"elapsed_ms\":\"[elapsed_ms]\",\"repo\":\"[tmp]/store\",\"resolved\":{\"[head]\":\"[head]\",\"main\":\"[theirs]\"}},\"ok\":true,\"op\":\"rebase\",\"result\":{\"base\":\"[c1]\",\"changeset\":\"[rebased]\",\"files_changed\":1,\"onto\":\"[theirs]\",\"root\":\"[id5]\",\"status\":\"rebased\"}}",
        "type": "text"
      }
    ],
    "isError": false,
    "structuredContent": {
      "api": 1,
      "meta": {
        "auth": "trust",
        "elapsed_ms": "[elapsed_ms]",
        "repo": "[tmp]/store",
        "resolved": {
          "[head]": "[head]",
          "main": "[theirs]"
        }
      },
      "ok": true,
      "op": "rebase",
      "result": {
        "base": "[c1]",
        "changeset": "[rebased]",
        "files_changed": 1,
        "onto": "[theirs]",
        "root": "[id5]",
        "status": "rebased"
      }
    }
  }
}
```

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 `rebase`, 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 rebase`](../commands/rebase.md#return-information) returns.

## Errors

A failed call is a tool result with `isError: true`; the envelope's `error.code` is one of the [error codes](../errors.md).

- [`E_INVALID_ARG`](../errors.md#e_invalid_arg): arguments that do not fit `RebaseReq`, a field named twice among them included, or that break one of the server's own rules.
- [`E_IDENTITY_REQUIRED`](../errors.md#e_identity_required): the server runs with no identity.
- [`E_NOT_A_REPO`](../errors.md#e_not_a_repo): the server's store is not there; the server serves on.
- [`E_INTERNAL`](../errors.md#e_internal): the operation panicked, a bug.

Then the errors of the operation, as [`swarmops rebase`](../commands/rebase.md#errors) lists them.

## See also

- [`swarmops rebase`](../commands/rebase.md)
- [MCP tools](README.md)
- [MCP integration](../../develop/mcp.md)
- [Error codes](../errors.md)
