New to git? Start here — the eight commands this page uses
New to git? Start here — the eight commands this page uses
This page assumes you have used git before. If you have not, here is the whole vocabulary
you need for XanoTS, in the order you will meet it. Nothing else on this page uses a command
that is not in this list.The Both hosts have a CLI that skips the website entirely:Install: cli.github.com, then Working alone? You can skip branches and pull requests entirely — commit straight to
The loop is: switch → edit → add → commit → push. Repeat as often as you like; a commit
is cheap and local until you push.A branch is the unit of work. You start one per change (
git switch -c add-orders-api),
commit to it freely, and it never affects main until it is merged. That is what makes it
safe to experiment.A pull request (GitHub) or merge request (GitLab) is how a branch gets reviewed
before it becomes part of main. It is not a git command — it happens on the website:1
Push your branch
-u origin <name> part is only needed the first time you push a given branch; after
that, plain git push works. The output prints a URL — open it and you land on the
“create pull request” (GitHub) or “create merge request” (GitLab) page with everything
filled in.2
Describe it, and paste your ephemeral URL
Say what changed and why. Paste the URL
xanots deploy printed, so your reviewer can
click through a running copy instead of reading a diff.3
Someone reviews it, then it merges
They comment or approve; you push more commits to the same branch if needed. Merging is
a button on that page. Afterwards, get the merged work locally:
- GitHub (gh)
- GitLab (glab)
gh auth login once.main. Everything else on this page still applies, because xano.lock conflicts and renames
come from merging, which you are not doing. Come back when someone joins you.For anything beyond this, the GitHub “Hello World” guide
is 10 minutes and covers branches and pull requests properly, and
Learn Git Branching teaches the branch model interactively.What goes in git
Commit
xano/** (your defs), xano.lock, package.json, package-lock.json, and your
frontend source.Never commit
.xano/auth.json, .env, node_modules, frontend/dist, and any exported bundle — a
bundle carries your workspace’s environment variable values.xanots login --local 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.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.
--frozen-lock in CI 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 XanoTS 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:
xanots export rebuilds this file from your source:
--ours sounds like it throws the other branch’s entries away, and on any other file it
would. It is safe only here, and only because of the export two lines below: that
command regenerates the whole lock from the merged code, so whatever you pick now is
discarded either way. Its only job is to get the conflict markers out of the file.Making git resolve it for you
Because the export can always rebuild the file,xano.lock is a reasonable candidate for a
union merge — git keeps both sides’ lines instead of raising a conflict, and your next export
tidies it:
This trades a conflict for a possibly-messy file that the next
xanots export normalizes. Do
not use merge=ours or merge=theirs — 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.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 both sides and re-export. 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.
Reviewing a XanoTS 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, and no flag is required for it to happen. The release
preview names each column that would be dropped and asks — but by then the PR is merged.
Catch it in review.
2
Unexpected churn in xano.lock
Expected: new entries for new objects; a moved entry for a rename. Unexpected: entries
disappearing, or a guid changing for an object nobody touched. Either means an identity
is about to be lost — ask before approving.
3
Secrets in xano/workspace.ts
Environment variable values live inline there. A PR that adds one 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.
A release is safe to re-run
Worth knowing when a merge or a rerun leaves you unsure whether something landed. Before importing,release compares the bundle against the workspace object by object; when
everything already matches, nothing is sent — the plan prints no changes, the summary
reports "upToDate": true, and no updated_at moves.
So the recovery for “did that release actually happen?” is to run it again and read the plan.