Create Branches and Tags
Start independent work on a branch and record a fixed Project state with a tag.
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.