> ## Documentation Index
> Fetch the complete documentation index at: https://sdk.docs.xano.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Merge path

> Merge a local build straight into your workspace or a tenant with xanosdk deploy --to, with a dry-run preview, a prune scoped to what this project landed, staging on a Xano branch, and the guard against overwriting edits made in Xano.

`xanosdk deploy --to` skips the release and merges the build on your disk straight into your
workspace or a tenant. It has what the release flow does not: a plan preview, loss warnings,
and deletion with `--prune`. What it does not leave is a release, so there is nothing stored to
land again, on a second tenant, or later. Prefer [releases](/ship/releases) for anything you may
need to repeat.

Use the merge path when you:

* want to see the plan before anything is written;
* are deleting objects your project no longer defines (a release never deletes);
* are landing a project whose tables hold files, which a release cannot carry;
* do not use releases at all.

## Preview, then merge

```bash theme={null}
npx xanosdk deploy ./xano/index.ts --to workspace --dry-run   # print the plan, send nothing
npx xanosdk deploy ./xano/index.ts --to workspace             # merge into the live Xano branch
npx xanosdk deploy ./xano/index.ts --to tenant:prod           # ...or into a tenant
```

A merge adds new objects and updates existing ones. Nothing is deleted and no rows are written
unless you ask. Anything destructive, such as a dropped column, is previewed and confirmed
before it is sent. `--yes` skips the confirmation for CI; it never skips the preview. An
unchanged project is a no-op: the plan prints `no changes` and nothing is sent.

After a merge, commit `xano.lock`. It records what this project landed on that destination,
which is what `--prune` reads.

| Flag | What it does to the destination |
| - | - |
| *(none)* | Adds new objects and updates existing ones. |
| `--dry-run` | Prints the plan and sends nothing. |
| `--prune` | Also deletes objects this project landed there and no longer defines. |
| `--seed` | Writes the project's seed rows by id, overwriting a live row at the same id. |
| `--reset-data` | Empties every table the build carries. With `--seed`, resets and re-seeds. |
| `--branch <label>` | Lands on a new Xano branch instead of live. Workspace only. |
| `--set-live` | Makes that Xano branch live once the import lands. |
| `--backup-branch[=<label>]` | Snapshots the live Xano branch's logic first. |
| `--overwrite` | Deploys over objects changed in Xano since your last deploy or pull. |
| `--allow-shared-schema-changes` | Lands table changes that reach every Xano branch. |
| `--replace` | Wipes the whole workspace, every Xano branch included, and imports in its place. |
| `--allow-branch-deletion` | Lets `--replace` delete the workspace's other Xano branches. |

## Prune deletes only what this project landed

`--prune` deletes an object only when the **landing record** for that destination names it.
`xano.lock` keeps one record per workspace and per tenant, listing each object this project
actually wrote there. A table built in the Xano editor, or another project's function with the
same name, is never this project's to delete.

```bash theme={null}
npx xanosdk deploy ./xano/index.ts --to workspace --prune --dry-run   # see what would be deleted
npx xanosdk deploy ./xano/index.ts --to workspace --prune
```

A planned deletion outside the record is refused and nothing is sent (`SDK_PRUNE_OUT_OF_SCOPE`,
exit `2`). `--yes` cannot waive it. The record is only as good as the copy you commit: a fresh
clone with no record prunes nothing, and a deploy from CI records into CI's checkout. The remedy
for a refusal is one landing without `--prune`, then commit the lock.

<Warning>
  A table `--prune` deletes takes every row with it, and no flag prevents that. Read the preview
  before you confirm.
</Warning>

## Stage on a Xano branch

```bash theme={null}
npx xanosdk deploy ./xano/index.ts --to workspace --branch staging --dry-run   # preview against the new Xano branch
npx xanosdk deploy ./xano/index.ts --to workspace --branch staging             # land it, live untouched
npx xanosdk workspace branch set-live staging --expect-live v1.3.2             # serve it when you are ready
```

`--branch` creates the Xano branch as a copy of live and refuses a label that already exists
(`SDK_BRANCH_TAKEN`, exit `2`). A Xano branch stages **logic**, not schema: tables are shared by
every Xano branch, so a table change reaches live as it lands. The merge refuses a table change
on a Xano branch (`SDK_SHARED_SCHEMA_CHANGE`, exit `2`) until you pass
`--allow-shared-schema-changes`. Workspace settings (its name, preferences and workspace-level
middleware) are not per branch either, and a `--branch` deploy leaves them alone.

`--backup-branch` snapshots the live Xano branch first, so the way back is
`npx xanosdk workspace branch set-live <backup-label>`. That restores logic only: a column the
deploy dropped stays dropped, with its values. To keep data, read `droppedColumns` in the
`--dry-run` plan and keep the column in code until its data has moved.

## Edits made in Xano: the drift guard

`deploy --to workspace` reads what has changed on each side since the last deploy or pull. If an
object it would overwrite was edited in Xano since then, it refuses (`SDK_WORKSPACE_CHANGED`,
exit `2`) and lists the objects under `details.objects`. See what changed where:

```bash theme={null}
npx xanosdk workspace diff ./xano/index.ts
```

`changedThere` was edited in Xano, `changedHere` in your project, `changedBoth` on both sides.
Pull the Xano edit into the project and commit it, then deploy again:

```bash theme={null}
npx xanosdk pull workspace
```

To deploy over the edit anyway, pass `--overwrite`; the run warns and names what it overwrote.
A `--dry-run` refuses nothing and lists the objects under `changedInXano`.

The guard covers `deploy --to workspace` only. `promote` and `tenant deploy` do not run it. It
also does not refuse when the Xano branch has no baseline yet, or on a `--branch` deploy to a
new Xano branch. [Drift](/govern/drift) covers keeping both sides in step.

## Replace wipes the whole workspace

`--replace` clears the **workspace**, not the Xano branch you deploy to. Every Xano branch is
deleted, along with vault secrets, request history and saved versions, and only the live Xano
branch comes back from the import. So a replace is refused while the workspace has any non-live
Xano branch, and `--yes` does not cover it. Export the Xano branches you want to keep, or pass
`--allow-branch-deletion` once you accept the loss:

```bash theme={null}
npx xanosdk workspace export --branch v1.3.2
```

Tenants have no Xano branches, so none of this applies to `--to tenant:<name>`.

## Refusals

A refusal writes nothing, not even to `xano.lock`, and exits `2`. `--yes` cannot waive one,
because a taken identity is not a question about whether you want the plan applied.

| Code | Meaning |
| - | - |
| `SDK_IDENTITY_CONFLICT` | The destination uses a name for a different object, or a pinned public URL slug is held elsewhere. The message names the fix. |
| `SDK_PRUNE_OUT_OF_SCOPE` | `--prune` would delete something the landing record does not name. |
| `SDK_SHARED_SCHEMA_CHANGE` | A `--branch` deploy alters a table. |
| `SDK_WORKSPACE_CHANGED` | An object was edited in Xano since your last deploy or pull. |
| `SDK_BRANCH_TAKEN` | The `--branch` label already exists. |

[Exit codes and outcomes](/help/exit-codes-and-outcomes) lists every exit code.

## Next

[Across workspaces](/ship/across-workspaces): move a release to another workspace or instance.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.