New to git? The commands the workflow uses
New to git? The commands the workflow uses
A pull request is how a branch gets reviewed before it becomes part of
main. Push the
branch, then open one with the GitHub CLI:What goes in git
Commit
xano/** (your defs and xano/xano.lock), package.json, package-lock.json, and
your frontend source.Never commit
.xano/auth.json, .env, .secrets.json, node_modules, frontend/dist, and any
exported bundle. A bundle carries your workspace’s environment variable values.xanosdk login --local-auth adds .xano/auth.json to .gitignore for you. A scaffolded
project already ignores the rest; if you built the repo by hand, this is the minimum:
xano.lock, and why it is in the repo
xano/xano.lock freezes your workspace’s object identities: the guids a release matches on, plus
the canonical URL tokens of API groups and toolsets. It is what makes a release update in
place instead of duplicating.
It is worth understanding when it is merely convenient and when it is irreplaceable, because
that changes how carefully you treat a conflict:
You generally will not know which entries have diverged without looking, and a workspace
adopted wholesale from the UI is almost entirely divergent. So: commit it, always.
It also holds two records the code cannot rebuild:
landed, what this project landed on each
workspace and tenant (what deploy --to … --prune deletes by), and synced, the baseline
workspace diff uses to say which side changed.
npm run xano:check in CI (export --check --strict, which implies --frozen-lock) fails the
build if an export would change the lock, which catches someone who forgot to commit it, and
stops a canonical minted in a throwaway container from silently changing your public URLs.
Mint locally, commit the lock.Resolving a xano.lock conflict
This is the most common merge conflict in a Xano SDK repo, and it is almost always benign: two
branches each added entries, and git cannot tell that the additions are independent.
A conflict is git telling you two branches changed the same lines and it will not guess which
wins. It marks the spot in the file and waits for you:
- Under
objects, keep every entry from each side. - Under
landed, keep every entry from each side. - Under
synced, keep either side’s baseline for a Xano branch, or delete it. A missing baseline only meansworkspace diffcannot say which side changed until the next deploy or pull. - Delete the markers and fix the commas.
Do not take one side with
git checkout --ours or --theirs. It throws the other branch’s
entries away, and for an adopted or renamed object nothing in your code can bring them back.
Every command refuses a lock that still holds conflict markers, duplicate keys or broken JSON,
and says how to fix it.Making git resolve it for you
Git’smerge=union driver keeps both sides’ lines instead of raising a conflict. It works line
by line, not by JSON key, so on xano.lock it can leave a missing comma, or the same synced
key twice, and every command refuses that lock until it is fixed by hand. Resolve the conflict
yourself with the recipe above.
Do not use
merge=ours or merge=theirs either, because either silently discards one branch’s
identities, which for an adopted or renamed object is unrecoverable.Renames
Renaming an object in code looks like a delete plus a create to the engine, because the guid derives from the name. Moving the lock entry is what keeps it a rename:xano/xano.lock in the same PR as the rename. A rename whose lock change
is committed separately is a delete-and-create in whichever release lands first.
Two people renaming on different branches
The renames are independent (different entries), so this resolves like any other lock conflict: take the union of both sides. What breaks it is a rename that reachedmain
without its lock entry; the second branch then exports against a lock that no longer describes
reality. If an export warns about an orphaned entry after a merge, that is the signal: run
lock rename for the object it names before releasing.
If both branches renamed the same object (one to stock, the other to goods), the union
holds one guid under two keys, and every command refuses it, naming both. Keep the name your
code exports and drop the other key. The guid stays under the name you keep:
Reviewing a Xano SDK pull request
Review the TypeScript like any other code, plus four things a normal code review misses, because they are invisible in a diff that looks routine.1
A removed table column, or a removed table
This is data loss on release. A tenant deploy replaces the tenant with the release, and
on a workspace tables are shared by every Xano branch, so either way the data is gone as
soon as the release lands. A tenant deploy names what it drops in a confirmation that
--yes skips, and promote refuses until someone adds --allow-shared-schema-changes.
In CI, neither stops anyone. Catch it in review.2
Unexpected churn in xano.lock
Expected: new entries for new objects; a moved entry for a rename; new
landed and
synced entries after a landing. Unexpected: entries disappearing, or a guid changing for
an object nobody touched. Either means an identity is about to be lost, so ask before
approving.3
Secrets in the workspace config
Environment variable names belong in
workspaceConfig({ env }) with an empty value; the
values live in the gitignored xano/.env. A PR that writes a real value into the config is
adding it to your git history permanently.4
The ephemeral URL actually works
The PR job leaves a live backend and frontend behind. Click it. A diff cannot tell you the
thing runs.
Did that release land?
Worth knowing when a CI job or a rerun leaves you unsure. Do not re-run a release write blind: arelease create, tenant deploy or promote whose answer was lost exits 9 and prints a
resolveWith command, and a retried release create can leave a second release under a
suffixed name. Run the resolveWith command, then look:
--branch <label> to compare a Xano branch that is not live. Under --json, the
differences are split by which side moved since they last matched (the baseline under
synced in the lock): changedThere (edited in
Xano), changedHere (edited in this project), and changedBoth (edited on both sides, a
conflict to reconcile by hand).
deploy --to workspace reads the same baseline before it writes. It refuses to overwrite an
object that changed in Xano (exit 2, SDK_WORKSPACE_CHANGED) until you pull the change into
the project, or pass --overwrite to deploy over it. More in Drift.