Manage changes .md

To manage changes, you can use versioning, branching, an archive and the trash.

Versioning

You can make a new version of an artifact, transform, or collection by passing an existing key. For example, for an artifact:

import lamindb as ln
from pathlib import Path

Path("my_file.txt").write_text("v1")
artifact = ln.Artifact("my_file.txt", key="my_file.txt").save()

Path("my_file.txt").write_text("v2")
artifact_v2 = ln.Artifact("my_file.txt", key="my_file.txt").save()

artifact_v2.versions.to_dataframe()  # see all versions of this artifact

This works because Artifact, Transform, and Collection inherit from IsVersioned.

Branching

All primary objects like artifacts, records, transforms, etc. (any that inherit from SQLRecord) have a branch field that determines their life cycle.

There are three built-in branches: main, trash, and archive. By default, objects are created on the main branch and visible in queries and searches.

lamin list branch
ln.Branch.to_dataframe()

Archive & trash

If you delete an object, it gets moved into the trash. There, it’s hidden from queries and search and scheduled for deletion.

artifact.delete()
trash = ln.Branch.get(name="trash")
assert artifact.branch == trash

# the artifact does not show up in a default query
ln.Artifact.filter(key="my_file.txt")

# you can still query for it by adding the trash branch to the filter
ln.Artifact.filter(key="my_file.txt", branch=trash)

# you can restore it from trash
artifact.restore()

To move an object into the archive, run:

archive = ln.Branch.get(name="archive")
artifact.branch = archive
artifact.save()

# you can still query for it by adding the archive branch to the filter
ln.Artifact.filter(key="my_file.txt", branch=archive)

Objects in the archive are hidden from queries and search but they are not scheduled for deletion.

Contribution workflow

Create a branch

To create a contribution branch and switch to it, run:

lamin switch -c my_branch

This configures a default branch in your environment that takes effect in shell, Python, and R sessions. All objects you create are then created on that branch.

Alternatively, you can configure a branch via the API:
ln.setup.settings.branch = "my_branch"  # equivalent to lamin switch my_branch via CLI
ln.track(branch="my_branch")  # default branch for all objects created in a run on my_branch
ln.Artifact(..., branch="my_branch")  # add an artifact on my_branch
ln.ULabel(..., branch="my_branch")  # add a ULabel on my_branch

Open a Change Request

Open the branch in the Changes page, and use the “Make change request” button to set it to “draft.”

Once you think the branch is ready, use the “Mark ready for review” button to submit it for review.

lamin update branch --status draft  # for current branch
lamin update branch --name my_branch --status review  # for any branch
branch = ln.Branch.get(name="my_branch")
branch.status = "draft"
branch.save()

branch.status = "review"
branch.save()

Merge a branch

To merge your contribution branch into the main branch, set the “Target Branch” dropdown to main and use the “Merge” button.

lamin switch main  # switch to the main branch
lamin merge my_branch  # merge contribution branch into main
ln.setup.merge("my_branch", target="main")

Work with branches

To see the current branch along with other information, run:

lamin info

Add notes to a branch:

lamin annotate branch --readme README.md

Comment on a branch:

To comment on the current branch, run:

lamin annotate branch --comment "I think we should revisit this, tomorrow, WDYT?"

To describe the current branch (optionally include comments), run:

lamin describe branch --include comments

To see on which branch a SQLRecord object was created, run:

sqlrecord.created_on

Just like Pull Requests on GitHub, branches are never deleted so that the provenance of a change stays traceable.

For the API reference, see Branch.