> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensorlake.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Commits

> List commit history with landing attribution, read per-commit diffs, and inspect workspace and repository graphs from the CLI or over HTTP.

Repository history is queryable without a clone. Two surfaces cover it:

* **CLI**: `tl git log` and `tl git smartlog` for humans and agents working at a mount or a terminal.
* **HTTP API**: commit listing, per-commit diffs, workspace logs, and repository graphs for control planes and dashboards. This is the same API the Tensorlake dashboard uses.

Commits that landed through Tensorlake carry **landing attribution**: how the commit reached the branch (`push`, `promote`, `merge`) and which actor did it, classified as a human or an agent.

<Note>
  In a **clone**, `git log`, `git diff`, and `git show` work as usual; Tensorlake is a normal remote. This page is for when there is no checkout: mounts, control planes, CI, and dashboards.
</Note>

## History from the CLI

### Workspace history: `tl git log`

`tl git log` shows the active snapshot chain of a workspace, plus any retained recovery chains created by rebases:

```bash theme={null}
$ tl git log /work
workspace 3f9a2b7e1c4d
  8b21f6a9 add notes
  5d0c7e2a resolve parser conflict
  4f8c2a17 initial app
```

* With a **mount path**, it logs that mount's workspace.
* With a **repository name**, it logs every workspace in the repository.
* With no argument, it uses the mount containing the current directory.

A read-only view has no workspace and no snapshot chain; use `tl git smartlog` there. Add `--json` for the raw pages.

### Repository graph: `tl git smartlog`

`tl git smartlog` shows branch, tag, workspace, snapshot, and mount positions in one view — where everything is, and how far each workspace is ahead of its base:

```bash theme={null}
$ tl git smartlog agent-outputs
repository project_9f3c2a1b/agent-outputs
main             1c4d9a2f  2h ago
├─ 3f9a2b7e1c4d  8b21f6a9  add notes                      ahead 2
└─ 7c2e9b4d1a6f  (no snapshots)                           at base
```

Unlike `tl git log`, smartlog works on read-only views: it reads repository state, not a workspace. Add `--project` for the bounded project-wide graph across every repository, and `--json` for the raw node/edge pages.

## List Commits over HTTP

```text theme={null}
GET /project/{project}/repos/{repo}/commits
```

The endpoint walks a branch's first-parent history and returns one page of commits, each with landing attribution when available. Authenticate with a short-lived Git credential over HTTP Basic auth (a read-scoped credential is enough):

```bash theme={null}
TOKEN=$(tl git token agent-outputs --json | jq -r .token)

curl -u t:$TOKEN \
  "https://git.tensorlake.ai/project/project_9f3c2a1b/repos/agent-outputs/commits?ref=main&limit=2"
```

```json theme={null}
{
  "repo": "project_9f3c2a1b/agent-outputs",
  "ref_name": "refs/heads/main",
  "items": [
    {
      "oid": "1c4d9a2f7e5b...",
      "subject": "add notes",
      "author_name": "Agent User",
      "author_email": "agent@example.com",
      "author_at_secs": 1756000000,
      "committed_at_secs": 1756000000,
      "parents": ["4f8c2a17b9d3..."],
      "landing": {
        "via": "promote",
        "actor": { "name": "api-key:key_7d2f9a1c", "kind": "agent" },
        "source_workspace_id": "3f9a2b7e1c4d",
        "source_snapshot": "8b21f6a9c3d5..."
      }
    },
    {
      "oid": "4f8c2a17b9d3...",
      "subject": "initial app",
      "author_name": "Agent User",
      "author_email": "agent@example.com",
      "author_at_secs": 1755990000,
      "committed_at_secs": 1755990000,
      "parents": [],
      "landing": {
        "via": "push",
        "actor": { "name": "user:diptanu", "kind": "human" }
      }
    }
  ],
  "truncated": false
}
```

### Query Parameters

| Parameter | Meaning                                                                                     |
| --------- | ------------------------------------------------------------------------------------------- |
| `ref`     | Branch name, full `refs/...` name, or a full 40-hex commit. Defaults to the default branch. |
| `via`     | Only commits that landed through this operation: `push`, `promote`, or `merge`.             |
| `actor`   | Only commits landed by this actor, matched against `landing.actor.name` exactly.            |
| `after`   | Opaque resume cursor from a previous page's `next_after`.                                   |
| `limit`   | Page size, clamped to 1–200. Default 50.                                                    |

Pagination is cursor-based: while `truncated` is `true`, pass `next_after` back as `after`. Filters apply server-side, and a filter that matches nothing still terminates promptly with a resumable cursor instead of walking unbounded history. An unknown `ref` returns `404`.

### Landing Attribution

The `landing` object records how a commit reached the branch:

| Field                 | Meaning                                                                               |
| --------------------- | ------------------------------------------------------------------------------------- |
| `via`                 | The operation that landed it: `push`, `promote`, or `merge`.                          |
| `actor.name`          | The authenticated principal that ran the operation.                                   |
| `actor.kind`          | `human` (a user or personal access token), `agent` (a project API key), or `unknown`. |
| `source_workspace_id` | For promotions: the workspace the commit came from.                                   |
| `source_snapshot`     | For promotions: the workspace snapshot that was published.                            |

Attribution comes from the repository's bounded operation log, so one landing entry attributes an entire pushed range — a large push costs one entry, not one per commit. Commits older than the attribution window come back without `landing` rather than erroring.

Filtering makes activity questions one call. Every commit an agent promoted to `main`:

```bash theme={null}
curl -u t:$TOKEN \
  "https://git.tensorlake.ai/project/project_9f3c2a1b/repos/agent-outputs/commits?ref=main&via=promote"
```

## Commit Diff over HTTP

```text theme={null}
GET /project/{project}/repos/{repo}/commits/{hash}/diff
```

Returns one page of a commit's line-level diff against its **first parent** (a root commit diffs against the empty tree), paged by file path with the same `after`/`limit` cursor scheme:

```bash theme={null}
curl -u t:$TOKEN \
  "https://git.tensorlake.ai/project/project_9f3c2a1b/repos/agent-outputs/commits/1c4d9a2f7e5b.../diff"
```

```json theme={null}
{
  "repo": "project_9f3c2a1b/agent-outputs",
  "commit": "1c4d9a2f7e5b...",
  "parent": "4f8c2a17b9d3...",
  "files": [
    {
      "path": "README.md",
      "change": "modified",
      "mode": 33188,
      "old_oid": "a94c8fe5...",
      "new_oid": "d3b07384...",
      "old_size": 16,
      "new_size": 31,
      "binary": false,
      "added_lines": 2,
      "removed_lines": 0,
      "patch_omitted": false,
      "hunks": [
        {
          "old_start": 1,
          "old_lines": 1,
          "new_start": 1,
          "new_lines": 3,
          "lines": [
            { "op": " ", "text": "# Agent Outputs" },
            { "op": "+", "text": "" },
            { "op": "+", "text": "## Parser Notes" }
          ]
        }
      ]
    }
  ],
  "truncated": false
}
```

* `change` is `added`, `modified`, or `removed`.
* Hunk line `op` is `"+"`, `"-"`, or `" "`, like a unified diff.
* Binary files are reported honestly: `binary: true` with sizes and oids, and no fabricated line hunks.
* A text file over the patch size caps comes back with `patch_omitted: true` and its line counts, so listings stay bounded on any commit.

## Workspace Log and Smartlog over HTTP

The same data behind the CLI views is available directly.

**Workspace log** — the active snapshot chain and retained recovery chains of one workspace:

```text theme={null}
GET /project/{project}/repos/{repo}/workspaces/{id}/log
```

Each active-chain entry carries `oid`, `subject`, `at_ms`, `actor`, `operation`, and `conflicted`. Retained chains (created when a rebase replaces a snapshot chain) carry the recovery ref, head, base, and retention reason — nothing is silently discarded by a rebase.

**Smartlog** — a bounded node/edge graph of branches, tags, workspaces, snapshots, and live mounts:

```text theme={null}
GET /project/{project}/repos/{repo}/smartlog
GET /project/{project}/smartlog
```

Nodes carry a `kind` (`branch`, `tag`, `workspace`, `snapshot`, `mount`), position (`oid`), actor, and timestamp; edges connect them. The project-wide form covers every repository in the project and supports `repo=` and `workspace=` filters — this is the fleet view for a control plane watching many agents at once. Both endpoints page with `after`/`limit`.

## Operation History

Separately from commit history, every repository keeps a durable operation log: pushes, promotions, merges, snapshots, branch deletions, and lifecycle events, each attributed to its actor. It is available from the SDKs as `operations(repo)` — see [Repository SDKs](/git/repository-sdks).

## Next Steps

<CardGroup cols={2}>
  <Card title="Repository Mounts" icon="folder-tree" href="/git/workspace-mounts">
    The snapshot and promote workflow that produces attributed history.
  </Card>

  <Card title="Merging Changes" icon="code-merge" href="/git/merging">
    Land workspaces on moved branches and query structured conflict records.
  </Card>

  <Card title="Repository SDKs" icon="rectangle-code" href="/git/repository-sdks">
    Repository operations and the operation log from Python or TypeScript.
  </Card>

  <Card title="Authentication" icon="key" href="/git/authentication">
    Short-lived Git credentials, scopes, and token lifetime.
  </Card>
</CardGroup>
