ServicesCatalog

Create Branches and Tags

Start independent work on a branch and record a fixed Project state with a tag.

Available

Before a training run starts, tag the commit that it reads, for example training-v7. The tag never moves, so anyone can rerun the job on the same data. When you want to try changes without affecting readers of main, create a branch. Neither copies Table data: a branch and a tag are names for a commit.

Before you start

  • A Project demo.
  • An access token in $SPIRAL_TOKEN. See authentication.

Create a branch

Name the new branch and the commit that it starts at. The target is a commit selector, so it can name a commit, a branch head, or a tag.

request = CatalogCreateBranchRequest(
    name="experiment",
    target=CatalogCommitSelector(branch=CatalogBranchTarget(branch="main")),
    idempotency_key="create-experiment-2026-10-13",
)
branch = client.catalog.create_branch("demo", request)
print(f"created {branch.branch_id} at {branch.head_commit_id}")

The response is the new branch with its branchId and headCommitId. Branch names can contain /, for example team/curated. Each segment between slashes must be non-empty, must not be ., and must not contain control characters.

The idempotency key makes a retry safe. A retry with the same key and request returns the first result. The same key with a different request fails.

Create a tag

Name the tag and the commit that it records:

request = CatalogCreateTagRequest(
    name="training-v7",
    target=CatalogCommitSelector(commit=CatalogCommitTarget(commit_id=commit_id)),
    idempotency_key="tag-training-v7",
)
tag = client.catalog.create_tag("demo", request)
print(f"{tag.name} records {tag.commit_id}")

Tag the exact commit that your workflow read. A branch target resolves to the head at the time of the request, which can be newer than the state that you used.

Verify the result

List the branches and the tags of the Project:

for branch in client.catalog.list_branches_items("demo"):
    print(f"branch {branch.name} at {branch.head_commit_id}")
for tag in client.catalog.list_tags_items("demo"):
    print(f"tag {tag.name} at {tag.commit_id}")

Both lists are paged. Pass the returned nextPageToken as pageToken to read the next page. Branches can change while you page through them, so the list is not a consistent snapshot; read a commit when you need one.

Rename and delete branches

Rename a branch with POST /api/catalog/projects/{project_id}/branches/{branch_id}/rename; the branch keeps its ID. Delete a branch with POST /api/catalog/projects/{project_id}/branches/{branch_id}/delete. A deleted branch keeps its commits and its history events. Tags cannot be moved, renamed, or deleted.

A typed Rust API to create branches and tags is planned. Today, the Rust SDK pins branches and reads commits. See Select an exact state.

The Catalog HTTP reference lists the request fields and errors for each operation.

Found a problem? Edit this page or report an issue.

On this page