main, staging, or
feature-login. Every build belongs to one branch, and the test runs, sessions,
and Atlas evidence that come from a build stay with its branch. Each app starts
with a base branch, which is the app’s default branch until you choose another.
Branch names are unique within an app and case-sensitive, up to 255 characters,
with no whitespace at either end and no control characters. iOS and Android apps
have separate branches.
What branches are for
- A source-of-truth Atlas for
main. After each merge, have CI buildmain, upload it with--branch main, and explore that build. Atlas scoped tomainthen maps the app you ship, without feature work mixed in. See Keep main or staging current. - Feature work kept apart. Upload in-progress builds with
--branch feature-login. Runs and links that usemainkeep using its builds. - Tests on a chosen branch. Run a test or workflow on a branch once, or save the branch on it so every run uses that branch. See Test a branch.
maincompared with a feature branch. Switch Atlas between the two, compare a build from each, or run the same workflow on both. See Compare two branches.- A steady release candidate. Pin
stagingto one build withrevyl app branch pin. Uploads move a pin only with--pin, so runs that usestagingkeep that build while newer builds arrive.
How a run picks its build
- A choice for this run, such as
--branch staging,--build-id, or a branch or build picked in a run dialog. - The saved selection of the test, workflow, or embed.
- Default branch, which uses the app’s default branch.
revyl app branch pin, --pin on an upload, or a build’s pin action in the
dashboard, such as Pin “staging” to this build. A usable build isn’t
deleted, is the artifact type the app runs (a simulator .app for iOS, an
.apk for Android), and isn’t one the Revyl GitHub App built to review a pull
request. Latest build is the most recently uploaded usable build.
Default branch is evaluated when a run starts, so it follows a later change of
the app’s default branch. A saved branch or exact build stays fixed. Once a run
starts, its branch and build stay fixed, including retries.
If the chosen branch doesn’t exist, has no usable build, or is pinned to an
unavailable build, the run fails instead of using another branch or
build, and the error names the branch and the app, such as
Branch "staging" on "My App" has no usable build. Upload a build to that branch, or
choose another one. Uploading to a branch that doesn’t exist creates it.
Uploads never pin a branch unless you ask. Builds from revyl build (local or
remote), revyl build upload, revyl init, and revyl dev (local or
--remote, including every rebuild), Expo imports, file uploads in the
dashboard, the GitHub upload-build action, MCP, the terminal UI, and API
uploads land on their branch. A branch that follows Latest build then uses the
new build, because it is the newest; a pinned branch keeps its pin.
To pin while uploading, pass --pin to revyl build or revyl build upload.
An API upload or remote build request pins its branch only when it sets
pin: true. You can also pin from the dashboard or with
revyl app branch pin. Deleting a branch’s pinned build puts the branch back
on Latest.
--set-current and --no-set-current are deprecated. --set-current still
pins, like --pin; --set-current=false and --no-set-current do nothing.
Each prints a warning on stderr, and --json output is unchanged.
Changing the app’s default branch doesn’t change saved selections. Apps created
before branches started with base pinned to the build they ran. When uploads
stopped pinning, every branch pinned to its newest usable build moved to
Latest build, so those branches now run each new upload. Pin a branch again
to keep it on one build.
Test a branch
Run once on a branch without changing any saved settings:revyl test build clear login returns a test to Default branch.
Compare two branches
Each branch keeps its own builds and Atlas evidence, so you can comparemain
with a feature branch directly:
-
Atlas map. In Atlas, pick a branch from the scope control and switch between
mainandfeature-login. Links keep the selected branch, so you can open the two side by side. From the CLI, pass--branch mainor--branch feature-logintorevyl atlas brieforrevyl atlas graph. -
Two builds. Compare the screens and transitions observed in one build from
each branch:
-
Test results. Run the same workflow on each branch and compare the
reports. Test history can be filtered by branch.
Manage branches
(default) in the table
and is_default in JSON, then the other branches by latest activity: a new
build, a pin or unpin, or a rename moves a branch up. DEFAULT BUILD shows
Latest build (v4) for a branch on Latest, with the version a run uses now, or
Pinned build (v1.2) for a pinned branch. BUILD ID is the build a
run on the branch uses now, or - when it has no builds. pin takes a build
ID, not a version label; revyl build list --app "My App" --branch staging
lists each build’s ID. Unpinning, or
deleting the pinned build, returns the branch to Latest. Saved
selections refer to branches by ID, so they survive a rename; scripts that pass
branch names need the new name. Branches can’t be deleted or archived.
Upload and list builds
--branch chooses the branch a build uploads to, and creates it if it doesn’t
exist. Use long-lived branches like main or staging. Don’t pass per-PR
values like ${{ github.head_ref }}; branches can’t be deleted. Without
--branch, uploads go to the app’s default branch. A newly created
app’s first revyl init upload uses its initial base branch; linked apps use
their default branch. revyl init --branch <name> overrides either choice.
A queued build or upload keeps its branch even if the app’s default branch
changes before it completes. Version
labels are unique within an app, so a label used on one branch can’t be uploaded
to another.
Each build also records the Git branch and commit it was built from, and the
CLI’s default version label starts with the Git branch name. These show where a
build came from. Pull request preview builds from the Revyl GitHub App compile
the pull request’s code and upload to the app’s default branch.
Build lists show all branches of the selected app by default. Pass --branch
to filter by one branch; --all-branches explicitly selects the default All
view. When no Revyl branch has the name you pass, the list filters each fetched
page by the Git branch the builds came from. The heading says which matched:
Builds (Revyl branch: main): or Builds (Git branch: main):. --branch HEAD
stands for your current Git branch; outside Git or on a detached HEAD it fails,
so pass --branch <name> or omit --branch to list every branch. Uploads and
runs treat HEAD and all as ordinary branch names. Cross-branch tables show
both GIT BRANCH and REVYL BRANCH. JSON keeps each build’s
branch identity and includes branch_filter only when a filter is applied.
Pagination still applies across the selected scope. An existing branch remains
browsable even when it has no usable build.
Upload results include branch_id and branch_name. Keep the returned build ID
to run that exact build later; a remote build job ID is not a build ID.
Without --pin, an upload doesn’t pin its branch. The upload result says which
build a run on the branch uses now:
staging (Latest build: runs use this upload),
staging (pinned to v1.2; runs that don't choose a build keep using v1.2) when
the branch is pinned, or staging (pinned to this build) after --pin.
Inspect the selected build
Userevyl build which to see the branch and build a run would use for one app,
without starting a run or changing its settings:
--branch, otherwise the app’s default branch, then that
branch’s default build: Latest build or its pinned build. Your local Git
branch does not change this selection. Explicit branch errors and unavailable
pins fail instead of selecting another build. HEAD is a literal branch name
here; omit --branch to use the app default.
This is app-level inspection. Saved test or workflow selections can choose a
different branch or exact build. The result describes selection now; a later
upload or settings change can change what a future run selects.
JSON stdout contains app_id, app_name, branch_id, branch_name,
branch_source (explicit_branch or default_branch),
build_id, build_version, and the current branch_build_selection
(latest or pinned).
A failed selection exits nonzero without printing a success object.
Browse builds in the terminal UI
The app build browser opens on All branches, including when you return to it. Use its branch filter to narrow the list; rows show their known branch names. The browsing filter does not choose the destination of an upload or the build for a run. Those actions keep their explicit, saved, and default selections. Pickers that choose a run, a saved selection, or an upload destination show the app’s default branch once, asDefault branch (base) with its default build,
followed by the other branches, most recently active first. A selection that
already names the default branch keeps that branch’s own row. The build choice
after a branch is Automatic, Latest build, or Exact build. Pickers
for runs, sessions, and saved test or workflow choices also list
All branches · Latest build after the default branch; the workflow run
picker offers it when you leave the branch name blank. Upload destinations and
the build browser don’t offer it.
Branch pickers, exact-build pickers, and the app’s build list show one page at a
time. Press m to load more choices. Press /, type a search, then press Enter
to search the full catalog within the selected scope. Submit an empty search to
clear it; Escape cancels editing the search. A failed later page leaves the
loaded choices available; press m to retry that page or R to refresh.
Run options
These options apply to one run and don’t change saved settings:--branch applies to each app the workflow runs. Each of those apps
needs a branch with that name and, unless you give it an exact build, a usable
build there; otherwise the workflow doesn’t start and the error names
the branch and apps. With test or workflow --build, --branch chooses
where the new build uploads, and the run uses that exact build. Runtime app
overrides replace the workflow’s saved app settings; platforms you don’t override
use each test’s saved selection. Don’t combine --build with --build-selection.
Device start/install and dev take an exact build with --build-version-id;
Explore and tests use --build-id. An exact build can’t be combined with
inherit or latest. Workflows take exact builds per platform with
--ios-build-id and --android-build-id, together with the matching app.
--all-branches on test run, workflow run, device start,
device install, and explore run uses the newest usable build across all of
the app’s branches: All branches · Latest build. It always uses Latest, so
it can’t be combined with --branch, an exact build (--build-id,
--build-version-id, --build, or a workflow’s per-platform builds), or a
--build-selection other than latest. Your Git branch doesn’t change it. A
dev loop follows one branch, which its rebuilds upload to, so revyl dev
doesn’t offer it. Run output names the branch each build came from, such as
Build: v1.4 from branch feature-login; JSON output includes branch_name.
Without --branch, --build-version-id, --build-selection, or --seed-latest,
a local revyl dev loop starts with the newest build on the app’s default
branch, even when the branch is pinned. An Expo or React Native loop first
looks for the newest one built from your current Git branch and prints a
warning when there is none. A dev context keeps its branch for detached startup
and every rebuild. --seed-latest uses the branch’s newest build, even when the
branch is pinned; --build builds afresh and --no-build never builds.
Installing another build on a device
doesn’t change the build the session started with in its history. revyl device history --app-id <id> --branch staging shows only sessions that started with a
build from that branch, and fails when the app has no branch with that name;
without --branch it shows every branch.
Saved selections
revyl test build show prints a test’s saved branch and build, such as
staging (<branch-id>) and Automatic; add --json for the saved IDs. Tests
saved with only a version label show that version without inventing a branch;
JSON includes pinned_version alongside the stored selector fields.
test create accepts the same --branch, --build-selection, --build-id,
and --all-branches choices, including when it creates a test from YAML or a
session. Workflows save iOS and Android separately with the --ios-* and
--android-* options; --ios-automatic saves Default branch for iOS, and
--ios-all-branches saves All branches · Latest build.
revyl workflow app show names each app and branch with its ID.
revyl workflow app disable turns a workflow’s app
override off and keeps its choices; revyl workflow app enable turns them back
on. revyl workflow app clear removes the choices, like turning the override
off in the dashboard.
In YAML, a test’s selection lives under test.build as branch_id,
build_selection, and pinned_build_id. An exact build needs both IDs and
build_selection: pinned. build_selection: latest_all_branches takes no
branch_id. Omitting the selection on a new test means Default
branch. When updating a test, omitting all three keeps its saved selection, and
build_selection: inherit with both IDs omitted resets it to Default branch. The
older pinned_version key is still accepted; YAML that includes both forms must
name the same build, branch, and version.
Atlas scope
atlas open show All branches by default. Pass --branch or
--branch-id to narrow the evidence, even for a branch with no usable build.
--all-branches explicitly selects All. --build latest uses the selected
branch’s newest usable build, or the app’s default branch when none is selected,
even when the branch is pinned. An exact build implies its branch, and an
explicit branch must match it. --build all means all branches and can’t be
combined with a branch. All retains authorization, pagination, time windows,
and recent-build limits within the selected app. A recent-build limit applies
once across the selected scope, not once per branch. Eligible legacy evidence
without a build appears only in All.
Branches filter evidence, not screens: merging or hiding screens and setting
identity roots apply to the whole app. Share links keep their scope. Merging a
pull request doesn’t move builds or Atlas evidence to another branch, and
uploading a build doesn’t explore it. To keep a shared main or staging Atlas
current after merges or on a schedule, use the
maintenance recipes.
MCP inputs
MCP tools that choose a build use the same choices:inherit (Automatic) for the branch’s default build,
latest for its newest build even when the branch is pinned,
latest_all_branches for the newest build across all of the app’s branches
(with no branch), and pinned with an exact build ID.
start_dev_loop doesn’t accept latest_all_branches. Inputs for one run
override saved selections, and Default branch uses the app’s default branch. A missing
branch or unavailable build fails instead of switching to another. run_test
and run_workflow results name each build and the branch it came from.
Exact build and branch inputs must agree. A choice for one run doesn’t save a new
default or pin. Read-only queries that resolve which build would run keep these
same selection rules. Saved branch IDs survive renames. See
MCP setup for installation.
API selection
Use branch IDs for saved references and names for one-off choices. Branch and build IDs must belong to the same app, and you must have access to it.
Saved test and workflow selections use
branch_id, build_selection, and
pinned_build_id. Embed requests keep build_id for an exact build. Runtime
request field names vary by endpoint, so check its published schema; an exact
build ID is never a remote build job ID. Atlas API reads accept branch_id;
omitting both branch and build reads every branch. The dashboard and CLI resolve
their selected scope before sending branch-scoped reads.