Database Commands
Overview
Section titled “Overview”rebase db is the family of commands that reach the project’s database. Each
one works on the database the project resolves, in the order
Database Branching lists:
--database-url, then DATABASE_URL in the shell, the branch the checkout is
switched to, DATABASE_URL in .env, --docker, and otherwise the managed
development database rebase dev starts. rebase db url prints which one that
is.
push, generate and migrate are described in depth on
Schema Generation, and every other command is in the
CLI reference.
Commands
Section titled “Commands”rebase db push
Section titled “rebase db push”Push schema changes directly to the database (development only):
rebase db push--database-url <url> names the database, and --docker the compose one, started
if needed. generate, migrate, branch, backup and restore take both too.
It leaves alone what your collections do not describe: other tables and views,
indexes you wrote, and the CHECK and EXCLUDE constraints on a collection’s
table, which a collection cannot declare. See
rebase db push for what it applies and
what it stops before.
rebase db generate
Section titled “rebase db generate”Generate SQL migration files from schema changes:
rebase db generateCreates timestamped migration files in drizzle/migrations/ that can be reviewed and committed.
rebase db migrate
Section titled “rebase db migrate”Run pending database migrations:
rebase db migrateApplies all unapplied migrations to the database.
On a database that has already booted, the first migration creates tables boot
already made, so the first db migrate there stops on already exists. Record
that migration as applied instead, once:
rebase db migrate --baseline <version>The version is the numeric prefix of the migration file; db generate prints the
command with it filled in. Every db migrate after that is an ordinary one. See
--baseline for a database that already
records migrations.
rebase db backup / backups / restore
Section titled “rebase db backup / backups / restore”rebase db backup --out ./backups # or s3://bucket/prefix, gs://bucket/prefixrebase db backups list # list what is storedrebase db restore ./backups/<file>.dump --yesbackup runs pg_dump; restore runs pg_restore and, being destructive,
asks for a typed yes on a terminal, or takes --yes; with no terminal and no
--yes it refuses and says to pass it.
Since 0.25 Into a database
that already holds what the backup creates, restore needs --clean. Without
it, it refuses before anything is applied, the cluster roles included, and
names the objects in the way and both ways round them: --clean, or
--create-db --target-db <new name>. On 0.24 it applied the roles and then
failed on pg_restore’s schema "rebase" already exists.
Since 0.25 restore refuses
the managed development database: a backup carries its rows as COPY data, which
it cannot receive, and on 0.24 the restore left it hung until it was stopped.
Restore into Postgres in Docker (rebase db restore <dump> --docker --clean --yes),
then rebase db pull --from "$(rebase db url --docker)" --yes copies it into
the managed database.
Since 0.25 Relative paths,
and the default ./backups, resolve against the directory you run rebase
from, so the three lines above meet in one directory; an option a command does
not take is refused before anything runs. On 0.24 the default is
backend/backups, so list it with --out ./backups.
Since 0.25 The dump and its roles file are readable by you only (0600), and
against a database that is not running, backup and restore print the
banner db push does. On 0.24 dumps are 0644.
Scheduling, the roles file that travels with each dump, and the restore procedure are in Backups and restore.
rebase db pull
Section titled “rebase db pull”Copy another database into the local development one:
rebase db pull --from postgres://… [--anonymize]--anonymize replaces personal fields on the way in, so a production copy can be
worked on locally without carrying real customer data onto a laptop. It matches
columns by name and is best-effort. Since 0.25
A column under a unique index gets a distinct value per row, and the pass is one
transaction: if it fails, the tables it would have rewritten are emptied and
named, and the command exits 1. On 0.24 it failed on token_hash once users had
signed in twice, leaving real data behind.
pg_dump strips privileges, so the copy would arrive with the source’s RLS
policies and none of the grants behind them — every read as rebase_user failing
with permission denied. The pull re-provisions the app role afterwards, using
the same routine boot and rebase db push use, so Rebase’s internal tables stay
revoked as they should be.
The target is always this project’s local development database and cannot be
chosen: --database-url is refused rather than accepted, so there is no way to
spell “pull into production”. --from is the only direction.
Since 0.25 A pull replaces
the local database’s contents: it empties each schema it copies first, so a
table that exists only locally does not survive it. Into the managed development
database the rows travel as INSERT statements, which it takes where COPY
would stop it. On 0.24 a pull into the managed database failed at the first
table and left it answering nothing until it was killed.
rebase db url
Section titled “rebase db url”Print the connection string this project is using, and nothing else, so it pipes:
rebase db urlpsql "$(rebase db url)"The managed development database is the case that needs this: .env leaves
DATABASE_URL commented out on purpose, and the port is derived from the
project path, so nothing on disk names it.
Since 0.25 It keeps that
port across a stop and a start, unless something else has taken it; on 0.24
every start picked a new one. When you have set a DATABASE_URL
of your own, that is what this prints — the resolution order is the same one
every other command follows. It starts the managed database if it is not
already running.
Since 0.25 After
rebase dev --docker, db url and the other commands use that Docker database
(and say so on stderr) until a rebase dev runs without the flag. The choice is
kept in .rebase/dev-database.json and ranks where --docker does, below every
connection string. A --docker you type that a connection string outranks
starts no container: one line on stderr says it was ignored, names what won,
and says how to reach Docker instead. A rebase dev --docker outranked that
way keeps the remembered choice as it was, so once the connection string is
gone the commands follow Docker again. On 0.24 every command needs its own
--docker, and an outranked one still starts the container.
Since 0.25 rebase init
gives each project its own compose port, from 5433–5632 by the project’s path,
and --docker checks that what answers on it is this project’s db container.
When another container or a Postgres outside Docker holds the port, it stops and
names it rather than logging in to someone else’s database. To move the
project, change the host port of the db service in docker-compose.yml, and
DATABASE_URL if .env sets one. On 0.24 every scaffold took the first free
port from 5432, so projects made side by side could share one.
rebase db stop / rebase db reset
Section titled “rebase db stop / rebase db reset”For the managed development database only:
rebase db stop # stop it; the data is keptrebase db reset # delete it and start overIt belongs to the project, not to the command that started it, so stopping
rebase dev leaves it running for the other commands. After 30 minutes with
nothing connected it stops itself, and the next command that needs it starts it
again. Since 0.25 rebase dev
says so as it stops, with how to stop the database now; on 0.24 it said nothing.
Since 0.25 db stop under a
running rebase dev says that its backend cannot reach the database until it
is back. The next command that needs it, rebase db url for one, starts it on
the same port, and the backend reconnects without a restart. On 0.24 it came
back on another port, and the backend answered 503 until rebase dev was
restarted.
rebase db branch
Section titled “rebase db branch”rebase db branch create <name>rebase db branch listrebase db branch info <name>rebase db branch switch <name> # work on it; every later command followsrebase db branch switch # say which branch you are onrebase db branch switch --off # back to the main databaserebase db branch delete <name>rebase db branch prune [--older-than 14d] [--include-dev-diff]PostgreSQL will not copy or drop a database anything else is connected to, and
the usual “anything else” is your own rebase dev. create and delete name
what is holding the database open; --force disconnects those sessions first.
Every branch is a full copy on disk, so they need clearing out. prune removes
three things: an entry whose database was dropped outside Rebase, a branch
database whose entry was never written, and — only with --older-than — branches
past an age you name. It asks before removing anything unless you pass --yes.
Since 0.25 With no terminal to ask on, such as in CI, it removes nothing, says to
pass --yes, and exits 1; on 0.24 it says “Nothing was changed.” and exits 0.
list and info only read: a database no branch was made on has none, and
they create no rebase schema there. On 0.24 they create the registry.
switch records the branch in .rebase/branch.json and never edits .env. It
takes precedence over DATABASE_URL in .env and loses to --database-url or a
DATABASE_URL in the shell, so a flag on the command line always outranks a
switch made earlier. delete refuses the branch you are on, since every command
in the checkout, the delete included, is pointed at it: switch --off first,
then delete it. The whole workflow is on Database Branching.
Related
Section titled “Related”- CLI reference — every other
rebasecommand - Schema Generation —
db push,db generate,db migrateanddb branchin depth - Backups and restore — scheduling, the roles file, restoring
- Database Branching — how a branch is made, and what it costs
- Scripts and the Console — the same database from a script or a REPL