Documentation menu

Branches and workspaces

The candidate model: why a branch holds a set of competing versions rather than a single pointer, and what a workspace is for.

This is the page where Nexa stops resembling Git. A branch here is not a pointer that moves forward, and understanding what it is instead explains the shape of nearly every command that follows. Both terms on this page build on versions, so read that page first if you have not.

What a branch is

A branch is a named context that holds a set of competing candidates — several versions offered as possible answers to the same question, coexisting. It is not a pointer to one version.

A Git branch is a single reference to a single commit, and moving it forward is the only thing it does; two answers to one question cannot both be on it. A Nexa branch holds all of them, and separately records which one is currently accepted.

nexa branch list shows each branch with the version it has selected:

Command
nexa branch list
Expected output
* main                 9a8fa956bb4d

Competing candidates

A candidate is a version offered as a possible answer within a branch or workspace. Recording one ordinarily both creates a version and selects it. Recording with --candidate creates it without selecting it, which is how you build a second answer alongside the first:

Command
nexa record --candidate -m "Alternative attempt"
Expected output
Created version dc1e69c9ae33
  workspace: main
  files:     1

Recorded as a candidate, not selected. Choose it with:
  nexa version select dc1e69c9ae33 --workspace main

Both versions now exist in the branch, and the listing marks which one is accepted:

Command
nexa version list
Expected output
* 9a8fa956bb4d  selected    device:31d2-a804-e396-299a
  dc1e69c9ae33  candidate   device:31d2-a804-e396-299a
Note: Why this is the central idea

Two people, or a person and an AI tool, attempting the same task in a pointer-based model produce a collision that must be resolved before either result can be stored. Here they produce two candidates, and reconciliation keeps both. Divergence adds a candidate rather than raising a rejection — which is what makes "try it two ways and decide afterwards" an ordinary operation rather than a merge conflict.

What a workspace is

A workspace is a development context inside a branch, in which several competing versions coexist. The intended grain is one workspace per problem, one version per attempt.

A workspace has properties a bare branch name does not:

  • an explicit owner, and members;
  • its own visibility;
  • a recorded origin when it was derived from another, so where it came from is part of the repository rather than a convention in its name.

A workspace cannot contain another workspace. Nesting is rejected rather than merely discouraged — the hierarchy is exactly two levels deep, always.

Who can see a workspace on Rinko Hub

Every workspace has a visibility. It is private unless whoever creates it chooses otherwise — it is never taken from the branch a workspace is placed in or the workspace it is derived from — and it can be changed afterwards. It means the same thing on the website, for nexa get and for nexa sync:

VisibilitySomeone who can read the repository but has no role on itRepository members
publicListed, readable, and brought by nexa get and nexa sync.Everything.
unlistedNot listed and not brought automatically. Readable, and brought, when they name it — so it is undiscoverable, not secret.Everything.
teamNot listed, not readable, not brought. Naming it answers as though it did not exist.Everything.
privateThe same as team today.Everything.

A member is anyone with a role on the repository: its owner, a collaborator, someone whose team has been given access, or a member of the organisation that owns it. In a private repository every workspace is visible to members only, whatever it says.

The primary workspace (main) has no visibility of its own. It is what the repository is, so it follows the repository: public when the repository is public.

Choose a visibility when creating a workspace, or change it later, on the repository's Workspaces tab or from the command line. Changing it needs the permission to manage the repository's workspaces — its owner, an admin or a maintainer.

Syntax
nexa workspace create preview --branch main --visibility unlisted
nexa workspace visibility preview public
nexa workspace list

A change applies to the website at once and to the next nexa get or nexa sync anyone runs. A workspace opened for a Contribution Request is private like any other, however the repository was created; what a contributor submits is shown by the Contribution Request itself.

Rinko Hub keeps more than one copy of every repository. Closing a workspace — making it visible to fewer people — is reported as done only once every copy has it; until then you are told it is still pending, and a copy that has not caught up turns people away rather than using the old setting. Opening a workspace reaches the copies one by one, and a copy that has not caught up simply goes on refusing for a moment.

Warning: Visibility is not encryption

Visibility decides what Rinko Hub lists and hands over from now on. It does not take back what someone already has, and it does not hide anything from the people a workspace is visible to. For content that must stay secret from some of the people who can reach a workspace, use a label, which encrypts it.

A protected file needs both. Someone reads it only if they may read the workspace it is in and hold the key for its label. Holding a label's key gets nobody into a workspace they cannot see: Rinko Hub does not hand them that workspace's protected files at all, on the website or through nexa get and nexa sync. Being able to see a workspace gets nobody into a label: they receive the file still encrypted.

Can read the workspaceHolds the label's keyA protected file in it
YesYesReadable
YesNoShown as protected; cannot be opened
NoYesNot available, as if it were not there
NoNoNot available, as if it were not there

Closing a workspace stops Rinko Hub handing its files to people without a role from then on, including protected files whose key they still hold. It cannot reach a copy somebody downloaded while the workspace was open.

Note: A branch is structurally a parentless workspace

Branches and workspaces are not two different kinds of object. A branch is a workspace with no parent, and the workspaces within it name it as theirs. That is why both hold candidates, both have a selected version, and both behave identically when you record into them — there is one concept here, seen at two levels.

nexa workspace list reports each workspace with how many candidates it holds:

Command
nexa workspace list
Expected output
* main  2 candidate(s)

Selecting a version

The selected version is the candidate a branch or workspace currently points at — its accepted state. Use that term rather than "tip" or "HEAD": selection is a mutable reference held by the branch, never a property of the version itself.

Selecting a different candidate says so explicitly:

Command
nexa version select dc1e69c9ae33
Expected output
Selected dc1e69c9ae33 in workspace `main`
Previous candidates are retained.

The previous selection is not deleted, and not overwritten. It becomes superseded — still present, still addressable, still part of the branch:

Command
nexa version list
Expected output
  9a8fa956bb4d  superseded  device:31d2-a804-e396-299a
* dc1e69c9ae33  selected    device:31d2-a804-e396-299a

Both versions remain, and the workspace still reports two candidates. Selecting again in the other direction would simply move which reference points where, changing nothing about either object. This is the practical payoff of everything on the previous page: because objects are immutable and references are the only mutable state, choosing is reversible and choosing is cheap.

Warning: Superseded does not mean discarded

A superseded version is a full, selectable state of the tree that happens not to be the accepted one right now. Nothing about it has been lost, and selecting it again restores it as the accepted state. There is no operation in Nexa that destroys a recorded version.

Next: the Development Root model, which is how these branches and workspaces appear as directories you can actually open.