Skip to content

Land a change

Landing is the everyday "ship it" verb. tovio land my-lane --into main integrates a lane's work onto a target lane and then automatically rebases every change stacked on top of it so your stack stays intact. Change IDs are preserved throughout — the work keeps its identity.

Landing is one undo away

tovio land, including its whole rebase cascade, is reversible as a single tovio undo. If a land isn't what you wanted, take it back in one command — the lane and every descendant return to where they were. See Undo and redo recorded operations for the local retention and peer-observation boundaries.

What's shipped, and what's still ahead

tovio land and the change/stack model are in the core today: landing with --into, the automatic (path-scoped) rebase cascade across a stack, op-logged and undoable lands, --dry-run and --explain previews, an opt-in linear --rebase land, and landing several lanes at once — all with Change IDs preserved throughout. Two parts on this page are still ahead: --async background landing (not in the shipped grammar), and the team-tier pre-land gates (proposal approval, required-check enforcement, policy clearance) that belong to lane protection and the Forge. Both are called out where they appear below.

flowchart LR
    L["tovio land my-lane<br/>--into main"] --> G{"land gates<br/>(conflict-free, policy,<br/>required plugins)"} 
    G -- pass --> M["main advances"] --> C[["Automatic rebase cascade<br/>chg:002, chg:003 re-parented<br/>Change IDs preserved"]]
    G -- block --> X[["✗ Blocked with reason<br/>+ next steps"]]

More diagrams for the full day-to-day loop: Branching, committing & merging workflows.

Land a change onto a lane

$ tovio land my-lane --into main
✓ landed `my-lane` into `main`  blake3:e9176f9d24…
  2 file(s) merged · same Change IDs — your work kept its identity · undo with `tovio undo`

--into names the target lane (default main); with no positional lane the source is the lane you're on. TOVIO advances the target to include your lane's work (and any not-yet-landed ancestors), writing a merge commit when the two have diverged, then re-parents the descendants. When main hasn't moved since you branched, the land is a plain fast-forward:

✓ fast-forwarded main → my-lane  blake3:e36deb9075…
  same Change IDs — your work kept its identity · undo with `tovio undo`

Preview before you land

tovio health says whether the current lane is clean, landable, and how stale it is. To see the whole decision — merge base, per-file algebra, gates — without advancing any ref, trace it:

$ tovio land my-lane --into main --dry-run --explain

That is the merge lens of tovio explain; --explain without --dry-run prints the trace and then lands for real.

The automatic rebase cascade

This is what makes stacked work painless. Say your lane my-lane sits on main, with two more changes stacked above it on a dependent lane:

Before:  main ─ my-lane (chg:001) ─ chg:002 ─ chg:003

Landing my-lane carries the rest along — no manual rebase:

$ tovio land my-lane --into main
✓ landed `my-lane` into `main`  blake3:e9176f9d24…
  2 file(s) merged · same Change IDs — your work kept its identity · undo with `tovio undo`
  Rebased 2 descendant change(s) on 1 lane(s): my-stack  (Change IDs unchanged)
After:   main (now includes chg:001)
              └─ chg:002 ─ chg:003       # auto-rebased, Change IDs unchanged

The line that matters: Change IDs unchanged. chg:002 and chg:003 are the same changes they were before — same stable names, new commit hashes. Anyone (you, a teammate, CI) can still point at "chg:002" and mean the same unit of work.

The cascade is path-scoped: a descendant lane whose files don't overlap what the integration changed is deliberately left alone and reported as such (N lane(s) left alone (no overlapping paths)), and a protected descendant lane is never rewritten — it is reported as NOT rebased with a tovio change rebase … --onto hint so you can re-stack it deliberately.

Conflicts never block the cascade

If a descendant can't rebase cleanly, TOVIO stores a conflict object and keeps cascading to the remaining descendants. The land still completes; the conflicted change keeps existing on top of the conflict and you resolve it when ready. The same holds for the land itself when the target is not a protected lane:

✓ landed `my-lane` into `main` with 1 conflict(s)  blake3:fd9764d8b6…
    ⚠ content       src/integrations/cgm/dexcom.ts

  nothing is blocked — the conflicts are stored as data.
  resolve them:   tovio resolve
  list them:      tovio status --conflicts

A conflict is data, not a failure — see Resolve conflicts.

Land linearly (--rebase)

By default a diverged land writes a merge commit, so each landed change survives verbatim as the reviewed, attested commit it was. If you want a linear mainline instead, --rebase re-derives the source lane's changes onto the target tip (Change IDs preserved) and fast-forwards:

$ tovio land my-lane --into main --rebase
✓ rebased `my-lane` onto `main`  blake3:a0594721d8…
  linear — same Change IDs, re-signed by you · undo with `tovio undo`

The cost is that each change is re-signed by you, the lander — which is why merge/fast-forward stays the default. --rebase is two-way only.

Land several lanes at once

List two or more source lanes and land folds them over their common base into one multi-parent commit — a native "octopus" land:

$ tovio land lane-a lane-b --into main

Land in the background (--async)

land is synchronous: it blocks until every descendant is re-parented, then prints one predictable summary. The CLI specification also designs an --async form that defers the cascade to a background operation and returns the terminal immediately, for rapid or agent-driven workflows.

Not yet available

--async is not in the shipped grammar; every land, including its cascade, runs synchronously today.

Landing onto a protected lane

Protected lanes like main or release are guaranteed buildable, so landing onto one requires a conflict-free change. If the change still has unresolved conflicts, the land is refused with TVO-CONFLICT-003 — no ref advances and no conflict object is written — and the message tells you how to proceed:

✗ Cannot land: 1 unresolved conflict(s)

  Landing `my-lane` into protected `main` leaves 1 unresolved conflict(s):
    content       src/integrations/cgm/dexcom.ts

  See where the branch stands:
    tovio health
  List the conflicts:
    tovio status --conflicts

  [TVO-CONFLICT-003]  https://tovio.dev/errors/TVO-CONFLICT-003

That is the three-part shape every TOVIO error uses: what happened, why, then the runnable next steps and the stable code. tovio resolve clears the conflicts; tovio change health <change-id> re-checks landability once you have.

On a protected lane, land is designed to run every configured pre-land gate and report each one, refusing only if a gate fails:

$ tovio land my-lane --into main
  Pre-land checks:
  ✓ Proposal approved (alice)
  ✓ No unresolved conflicts
  ✓ Required checks passed (build + tests)
  ✓ No policy-protected files modified without clearance
✓ Landed: chg:a3f7b2 → main @ gh1234

This gate is re-enforced server-side too, so it can't be skipped by pushing directly.

Conflicts can live in flight — they just can't land

A change in progress may carry conflicts and you keep working normally. The protected-lane gate only stops conflicts from reaching shared, must-build code. Landing onto an unprotected lane may carry conflicts, like any in-flight change.

Some pre-land gates are team-tier

The conflict-free gate, the exclusive-lock gate, and the semantic-check gate run locally today (tovio explain merge lists them under Gates). Proposal approval, required-check enforcement, and policy clearance belong to lane protection (tovio policy protect) and the Forge; the Forge and its pre-land gate are built and tested, but not yet run in production, and the checklist above is the designed rendering. See Collaboration & files for the proposal/review workflow.

Land vs. merge vs. rebase

  • land (everyday) — integrate a lane's changes onto a target lane and cascade the rebase to the stack. This is your primary "ship it" verb.
  • merge — the CLI specification designs a standalone tovio merge for combining two lanes; it is not implemented. land --into carries the same stored-conflict semantics.
  • rebase (advanced) — explicitly re-parent changes onto a new base. land is the everyday form of the same idea; see Rewrite history safely.

Where to go next

Last reviewed September 9, 2026

Suggest an improvement to this page Not for security reports — see disclosure