swarmops history#
List the changesets that changed a path, newest first, along first parents.
- Group
read- Since
0.1.0- Mutates
- no
- Identity required
- no
- MCP tool
path_history- Envelope op
path_history- Exit codes
- 026
Syntax#
swarmops history [OPTIONS] <REV:PATH>Required arguments#
Syntax: <REV:PATH>.
The revision and the path (a file, or a directory), split at the first ':'.
Optional arguments#
The command also takes the global options.
Syntax: -n, --limit <N>.
Default: 50.
The most changesets to list.
Syntax: --cursor <CURSOR>.
Resume a history: the previous page's cursor, exactly as it was returned.
Examples#
swarmops --repo [tmp]/store history main:src/lib.rs{
"ok": true,
"op": "path_history",
"api": 1,
"result": {
"path": "src/lib.rs",
"entries": [
{
"changeset": "[c3]",
"op": "put",
"kind": "file",
"id": "[id5]",
"author_agent": "agent/worker-17",
"created_at": "[created_at]",
"title": "c3"
},
{
"changeset": "[c1]",
"op": "put",
"kind": "file",
"id": "[id6]",
"author_agent": "agent/worker-17",
"created_at": "[created_at]",
"title": "c1"
}
],
"truncated": false
},
"meta": {
"repo": "[tmp]/store",
"elapsed_ms": "[elapsed_ms]",
"resolved": {
"main": "[c4]"
},
"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#
history follows one path back through first parents and lists every changeset that changed
what it holds, newest first, each with what the path held right after it: the blob or tree id
and its kind, or nothing. It answers "who changed this file, and to what", including who
deleted it.
What counts as a change#
A changeset is listed when its own changes, against its first parent, touch the path:
- for a file, a new content, a new kind (a file made executable, a symlink made a file), its addition or its deletion;
- for a directory, any of those below it.
Each entry's op is put when something is at the path after the changeset, with its kind
(file, exec, symlink or dir) and its id (a blob id, or a tree id for a directory), and
delete when nothing is. An executable bit changed alone gives a put whose id did not
change, under a new kind. author_agent, created_at and title are what log gives for the
same changeset.
The path does not have to exist at REV. A file deleted on main keeps its history: the newest
entry is its deletion, the ones below its earlier versions, each id readable with cat at that
entry's changeset.
The target#
REV:PATH is required; the target splits at the first :, as cat's does. One trailing / is
taken (main:docs/ is main:docs). REV alone is E_INVALID_ARG ("names no path"), and so is
an empty path or one with a leading /. Paths match whole components: main:src/lib is not
src/lib.rs.
A path that no changeset on the first-parent history of REV touched is E_PATH_NOT_FOUND
(exit 6), on the first page only, with the hint of the ls of the directory it would be in.
log --path with the same path gives an empty page instead.
Pages#
-n/--limit (50 by default, at least 1) cuts the page; a cut page gives cursor, the id of its
last entry, and --cursor continues from that changeset's first parent. REV is not read when a
cursor is given, but the path is, so give the same REV:PATH on every page. A cursor at the
path's oldest change gives an empty page, not an error. A cursor is a full changeset id the
store holds; anything else is E_INVALID_ARG.
Patterns#
- Blame a file.
history main:src/lib.rslists who changed it and when; for one entry,diff <changeset>~1 <changeset> --path src/lib.rs --format unifiedgives the lines it changed. - Restore a deleted file. The entry below the deletion holds the last content's blob id: read
it with
cat <that changeset>:<path>, or put it back with a commit whose change names the blob,{"blob": "<id>"}, which uploads nothing. - Watch a directory.
history main:docslists the changesets that changed anything underdocs, with the directory's tree id after each; two equal tree ids mean nothing below changed. - Through MCP, the tool is
path_history, withrev(mainwhen omitted),path,limitandcursor. Ask for 100 entries or fewer a call: see Result size limits.
Caveats#
- History follows first parents only, as
logdoes: a merge's other parents are never walked, and what a merge brought in shows as its own change. Native histories have no merges. - No renames: a file moved elsewhere ends in a
deletehere, and its history at the new path starts with aput. historyreads a derived value, the newest changeset on the chain that touched the path, which the first reader to ask for it derives: a walk back over the changesets that do not touch the path, stored with a memo every 64 changesets of a longer walk. The first history of a path on a long history pays that walk.swarmops derivedoes not derive these values ahead; a store that cannot be written answers all the same, without keeping them. A stored value that fails its checks isE_STORE_CORRUPT, with the hintswarmops verify --deep, and making room explains removing the derived values, which readers then derive again.
Guides#
- Reading and repairing history: Follow one path
- Concepts: Derived value
- Known limitations: Commits, refs and history
Return information#
result is a PathHistoryPage (swarmops schema PathHistoryPage prints its JSON Schema).
| Field | Type | Required | Description |
|---|---|---|---|
cursor | string or null | no | When truncated: where the next page continues. Opaque: pass it back as given, as the next request's cursor. |
entries | array of PathHistoryEntry | yes | The changesets that changed what it holds. |
path | string | yes | The path, without a trailing /. |
truncated | boolean | yes | Whether an older changeset that changed it follows this page. |
Envelope op: path_history.
Exit codes:
0: Success.2: The request or the command line is malformed.6: Something the request names does not exist.
Errors#
- E_PATH_NOT_FOUND (exit 6): The path does not exist at that revision.
- E_INVALID_ARG (exit 2): A malformed argument or request, including a command-line usage error.
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).