Datenbank-Branching
Übersicht
Abschnitt betitelt „Übersicht“Datenbank-Branching ermöglicht es Ihnen, sofortige, isolierte Kopien Ihrer gesamten Datenbank (sowohl Schema als auch Daten) zu erstellen, um Entwicklungs-, Migrationstests- und QA-Verfahren sicher durchzuführen.
Durch die Nutzung nativer PostgreSQL-Templates stellt Rebase geklonte Datenbanken auf Dateisystemebene bereit. Das bedeutet, dass Sie ein originalgetreues Replikat erhalten, das alle Tabellen, Indizes, benutzerdefinierten Typen, Constraints und Row-Level Security (RLS)-Richtlinien enthält – ganz ohne Netzwerkübertragungs-Overhead oder Verzögerungen bei der Schemaerstellung.
┌────────────────────────┐ │ Production DB (rebase) │ └───────────┬────────────┘ │ (CREATE DATABASE ... TEMPLATE) │ ┌─────────────────┴─────────────────┐ ▼ ▼┌───────────────────────┐ ┌───────────────────────┐│ rb_feature_auth (Dev) │ │ rb_staging (Staging) │└───────────────────────┘ └───────────────────────┘Unter der Haube: PostgreSQL-Templating
Abschnitt betitelt „Unter der Haube: PostgreSQL-Templating“Wenn ein Datenbank-Branch erstellt wird, führt der Rebase-BranchService folgendes SQL aus:
CREATE DATABASE "rb_feature_auth" TEMPLATE "rebase";PostgreSQL verarbeitet diesen Vorgang durch Kopieren der zugrunde liegenden Dateisystemverzeichnisse, die die Quelldatenbankdateien enthalten. Dies bietet:
- Klone in Sekundenbruchteilen: Es wird keine SQL-Generierung oder Datenladung durchgeführt.
- Identische Schemas und Daten: Jede Zeile, jeder Index und jeder Constraint wird sofort dupliziert.
- Vollständige Isolation: Das Ändern des Schemas oder das Einfügen von Datensätzen in den Branch hat keine Auswirkungen auf die Quelldatenbank.
Schutz vor Verbindungseinschränkungen
Abschnitt betitelt „Schutz vor Verbindungseinschränkungen“PostgreSQL setzt voraus, dass keine weiteren aktiven Verbindungen zur Template-(Quell-)Datenbank bestehen, wenn ein CREATE DATABASE ... TEMPLATE-Befehl ausgeführt wird.
Um Fehler zu vermeiden, führt der Rebase-DatabasePoolManager vor dem Klonen oder Löschen eines Branches einen aktiven Eviction-Prozess durch:
- Eviction-Schleife: Schließt und trennt automatisch alle ungenutzten Pools (Idle Pools), die innerhalb des Rebase-Anwendungskontexts auf die Zieldatenbank verweisen.
- Blockierung durch externe Verbindungen: Wenn externe Clients (wie DBeaver, pgAdmin oder externe Backend-Prozesse) aktive Transaktionen auf der Quelldatenbank aufrechterhalten, lehnt PostgreSQL die Template-Operation mit dem Fehler
"being accessed by other users"ab.
Die Fehlermeldung benennt genau, was verbunden ist, anstatt Sie raten zu lassen:
Cannot create branch: the source database "leadgen" has active connections. Connected right now: 2 × psql A running `rebase dev` is the usual one — stop it, or re-run with --force to disconnect them for you.--force beendet diese Sitzungen vor dem Templating, sowohl bei create als auch bei delete. Die Sitzung, die den Befehl selbst ausführt, wird dabei niemals beendet.
Der DatabasePoolManager trennt vor dem Klonen oder Löschen seine eigenen Idle-Pools – allerdings nur die Pools innerhalb des Prozesses, der die Arbeit ausführt. Da rebase db branch als eigener Prozess läuft, erreicht dies nichts anderes auf Ihrem Rechner:
- Ein laufendes
rebase devblockiert das Branching. Das ist der Regelfall, kein Randfall: Das Verlangen nach einem Branch und das Ausführen der App fallen meist zusammen. Stoppen Sie den Dev-Server, erstellen Sie den Branch und starten Sie ihn wieder. - Das gilt auch für jeden anderen Client. DBeaver, pgAdmin, eine
psql-Sitzung, eine zweite App-Instanz – PostgreSQL weist die Operation mitis being accessed by other userszurück, und diese Verbindungen müssen manuell geschlossen werden.
In PostgreSQL selbst führt kein Weg daran vorbei; CREATE DATABASE ... TEMPLATE ist eine Kopie auf Dateisystemebene, und das Template muss für die Dauer des Vorgangs im Ruhezustand sein.
Metadaten-Schema
Abschnitt betitelt „Metadaten-Schema“Branch-Konfigurationen werden in der Standarddatenbank in der Tabelle rebase.branches gespeichert, die während des Bootstrappings bereitgestellt wird:
CREATE SCHEMA IF NOT EXISTS rebase;
CREATE TABLE IF NOT EXISTS rebase.branches ( name TEXT PRIMARY KEY, -- Sanitize user branch name (alphanumeric & underscores) db_name TEXT NOT NULL UNIQUE, -- Actual PostgreSQL database name (prefixed with 'rb_') parent_db TEXT NOT NULL, -- Source database cloned from created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), metadata JSONB DEFAULT '{}');Ein Server, der auf einem Branch läuft, verwaltet Branches in der Datenbank, aus der der Branch
kopiert wurde. Die eigene rebase.branches des Branches ist nur ein Schnappschuss, aufgenommen bevor
seine Zeile geschrieben wurde. Deshalb setzt rebase dev in einem umgeschalteten Checkout
REBASE_BRANCH_PARENT_DATABASE auf die Datenbank, die .env nennt, und ein Server
mit dieser Variable liest und schreibt die Registry dort und kopiert neue Branches
standardmäßig aus ihr. Der Branches-Bereich von Studio listet auf einem Branch die Branches der Hauptdatenbank auf,
einschließlich des aktuellen, und ein dort erstellter Branch ist einer, den
rebase db branch list anzeigt.
Programmatische API
Abschnitt betitelt „Programmatische API“Die Branching-API wird über den BranchService des Backends bereitgestellt. Nachfolgend finden Sie eine Referenz der Kernschnittstelle:
Einen Datenbank-Branch erstellen
Abschnitt betitelt „Einen Datenbank-Branch erstellen“Erzeugt eine neue Branch-Datenbank aus der Standarddatenbank oder einem expliziten Quell-Template.
Der Standard ist die Datenbank, auf der die eigene Verbindung des Servers liegt, oder
REBASE_BRANCH_PARENT_DATABASE, wenn der Server auf einem Branch läuft. Es ist nie
die Datenbank, die ADMIN_CONNECTION_STRING nennt, wenn das eine andere ist.
import { initializeRebaseBackend } from "@rebasepro/server";
const backend = await initializeRebaseBackend({ /* ... */ });const admin = backend.driver.admin;
// Create a branch from the default databaseconst newBranch = await admin.createBranch("feature_oauth");
// Create a branch from a specific staging databaseconst stagingBranch = await admin.createBranch("pr_review_42", { source: "rb_staging"});Aktive Branches auflisten
Abschnitt betitelt „Aktive Branches auflisten“Ruft eine Liste der registrierten Branches zusammen mit ihren physischen Größen ab, die über die PostgreSQL-Systemfunktion pg_database_size abgefragt werden.
const branches = await admin.listBranches();/*Output:[ { name: "feature_oauth", database: "rb_feature_oauth", parentDatabase: "rebase", createdAt: 2026-06-20T22:00:00.000Z, sizeBytes: 83886080 // 80 MB }]*/database ist die PostgreSQL-Datenbank, die der Branch ist, so wie sein Eintrag sie angibt:
womit Sie sich verbinden und was Sie als source übergeben, um den Branch zu kopieren. Es ist nicht
der Name des Branches (staging ist die Datenbank rb_staging).
Branch-Informationen abrufen
Abschnitt betitelt „Branch-Informationen abrufen“Ruft Metadaten für einen einzelnen Branch ab. Wenn der Branch existiert, versucht der Dienst, dessen aktuelle physische Festplattenbelegung abzufragen:
const info = await admin.getBranchInfo("feature_oauth");Einen Branch löschen
Abschnitt betitelt „Einen Branch löschen“Löscht die Zieldatenbank vom Server und bereinigt deren Eintrag in der Metadatentabelle rebase.branches.
await admin.deleteBranch("feature_oauth");[!CAUTION] Schutzmechanismus: Die Hauptdatenbank (der in den Verbindungszeichenfolgen konfigurierte Standarddatenbankname) ist geschützt. Das ist die Datenbank, auf der die eigene Verbindung des Servers liegt, oder auf einem Branch
REBASE_BRANCH_PARENT_DATABASE. Wenn Sie versuchen, die übergeordnete Datenbank zu löschen, wirft derBranchServiceden Fehler"Cannot delete the main database"und bricht ab.
CLI-Integration
Abschnitt betitelt „CLI-Integration“Datenbank-Branches können direkt über das Rebase-CLI verwaltet werden.
# Create a new branch named 'dev_sandbox'rebase db branch create dev_sandbox
# Clone from a database other than the defaultrebase db branch create pr_review_42 --from rb_staging
# List all branches and disk utilizationrebase db branch list
# Work on it — every later command in this checkout uses itrebase db branch switch dev_sandbox
# Which branch am I on?rebase db branch switch
# Back to the main databaserebase db branch switch --off
# Show one branch's parent, age and sizerebase db branch info dev_sandbox
# Delete a branchrebase db branch delete dev_sandboxswitch macht einen Branch erst nutzbar. Es hinterlegt den Branch in .rebase/branch.json – nur den Namen, niemals einen Connection-String, sodass Ihre Anmeldedaten ausschließlich in .env verbleiben – und jeder nachfolgende rebase-Befehl in diesem Checkout verwendet stattdessen die Datenbank des Branches: dev, db push, db migrate, db backup.
In der Auflösungsreihenfolge steht es zwischen der Shell und der Projektdatei:
--database-urlin der BefehlszeileDATABASE_URLin der Shell-Umgebung- der Branch, zu dem dieses Checkout gewechselt hat
DATABASE_URLin der.env-Datei des Projekts--dockeroder der Umstand, dass das letzterebase devdamit lief- die verwaltete Entwicklungsdatenbank
Seit 0.25 Stufe 5 folgt dem letzten
rebase dev --docker, sodass ein Branch-Befehl danach kein eigenes --docker braucht,
und ein --docker, das eine Stufe darüber übertrumpft, startet keinen Container und
sagt, dass es ignoriert wurde. Unter 0.24 zählt nur das Flag, und ein übertrumpftes
startet den Container trotzdem.
Ein Branch muss Vorrang vor .env haben, da das Umschalten sonst bei keinem Projekt Wirkung zeigen würde, das DATABASE_URL setzt; er darf jedoch keinen Vorrang vor den beiden darüber liegenden haben, da ein Flag auf der aktuellen Befehlszeile eine unmittelbarere Anweisung ist als ein Wechsel am Vortag.
.rebase/ wird von Git ignoriert (gitignored), sodass der Branch, auf dem Sie sich befinden, nur für Ihren Rechner gilt und niemals für das gesamte Projekt.
Seit 0.25 In einem umgeschalteten
Checkout arbeiten rebase db branch create, list, info, delete und prune auf der
Hauptdatenbank, in der das Register liegt, und sagen das auch. create kopiert weiterhin
den Branch, auf dem du bist, außer du übergibst --from; er wird in der Hauptdatenbank
erfasst, sodass list ihn aus jedem Checkout anzeigt. Vor 0.25 tat das nur list, und
ein aus einem umgeschalteten Checkout erstellter Branch wurde allein im Snapshot des
Branches erfasst.
Branches sind ganz gewöhnliche PostgreSQL-Datenbanken, die nach dem Branch mit dem Präfix rb_ benannt sind. So entspricht dev_sandbox oben der Datenbank rb_dev_sandbox auf demselben Server.
Das Erstellen eines Branches ändert nicht, mit welcher Datenbank Ihr Projekt kommuniziert. rebase db branch create erstellt die Kopie und belässt es dabei; es wird nichts in .env geschrieben, und das nächste rebase dev verwendet weiterhin die zuvor genutzte Datenbank. Um mit einem Branch zu arbeiten, verweisen Sie selbst per DATABASE_URL darauf – der Connection-String entspricht dem vorhandenen, lediglich der Datenbankname wird ausgetauscht:
# .envDATABASE_URL=postgresql://user:pass@localhost:5432/rb_dev_sandboxBranching erfordert einen echten PostgreSQL-Server
Abschnitt betitelt „Branching erfordert einen echten PostgreSQL-Server“Branching funktioniert nicht mit der verwalteten Entwicklungsdatenbank – der konfigurationsfreien PGlite-Datenbank, die rebase dev startet, wenn ein Projekt keine DATABASE_URL hat.
PGlite bedient genau eine Datenbank. Ein CREATE DATABASE ... TEMPLATE darauf schreibt lediglich einen Katalogeintrag und kopiert nichts, sodass der „Branch“ auf dieselbe Datenbank verweist, von der er geklont wurde: Schreibvorgänge, von denen Sie glauben, dass sie isoliert sind, landen in Ihrer Entwicklungsdatenbank, und es gibt keine zweite Kopie, zu der Sie zurückkehren könnten.
Verwenden Sie Branching mit einem echten Server – Ihrer eigenen PostgreSQL-Instanz über DATABASE_URL oder rebase dev --docker, dem die Branch-Befehle dann folgen.
Best Practices und Einschränkungen
Abschnitt betitelt „Best Practices und Einschränkungen“Festplattennutzung
Abschnitt betitelt „Festplattennutzung“Da PostgreSQL die Dateien auf der Festplatte dupliziert, belegt jeder Branch genauso viel Speicherplatz wie die Quelldatenbank. Wenn Sie eine 100-GB-Produktionsdatenbank haben, verbraucht das Erstellen von 5 Branches zusätzliche 500 GB Speicherplatz.
- Empfehlung: Verwenden Sie Subsets von Datenbanken oder schlanke Dev-Templates als Klonquellen anstelle vollständiger Produktionsklone.
Mit rebase db branch prune geben Sie den Speicherplatz wieder frei:
rebase db branch prune # orphans only — always saferebase db branch prune --older-than 2w # and anything older than two weeksNichts läuft ab, es sei denn, Sie verlangen es: Ein Branch kann die einzige Kopie der Arbeit eines ganzen Nachmittags sein. Daher ist --older-than optional (Opt-in), Altersangaben werden abgerundet, und der Befehl zeigt seinen Plan an und fragt nach Bestätigung, bevor etwas entfernt wird – es sei denn, Sie übergeben --yes.
prune findet auch die beiden Fälle, in denen Branches von ihren Metadaten abweichen – ein Eintrag, dessen Datenbank mit einfachem SQL gelöscht wurde (was list für immer weiter melden würde), und eine Branch-Datenbank, deren Eintrag nie geschrieben wurde (bei einem Absturz zwischen den beiden Anweisungen, die create ausführt). Atlas’ temporäre <db>_dev_diff-Datenbanken werden ebenfalls gemeldet, aber nur mit --include-dev-diff entfernt: Sie sind keine Branches, und eine davon könnte zu einem gerade laufenden db push gehören.
pgBouncer-Kompatibilität
Abschnitt betitelt „pgBouncer-Kompatibilität“Stellen Sie beim Einsatz hinter pgBouncer oder Connection-Poolern sicher, dass der Pooler administrative Datenbankoperationen unterstützt. Das Erstellen und Löschen von Datenbanken umgeht standardmäßige Pools auf Transaktionsebene und erfordert direkte Verbindungen zum Postgres-Server (mit erweiterten Benutzerrechten) über die adminConnectionString-Konfiguration.
Datenbankübergreifende Abfragen
Abschnitt betitelt „Datenbankübergreifende Abfragen“Da Branches separate PostgreSQL-Datenbanken sind, können Sie keine SQL-JOIN-Anweisungen über Branch-Grenzen hinweg ausführen. Alle Relationen müssen sich innerhalb der Grenzen der einzelnen aktiven Branch-Datenbank befinden.
Verwandte Themen
Abschnitt betitelt „Verwandte Themen“- Datenbank-Befehle —
rebase db branchund dessen Flags - Schema-Generierung — wie das Schema erzeugt wird, das ein Branch kopiert
- Umgebung & Konfiguration —
DATABASE_URLund worüber ein aktiv geschalteter Branch Vorrang hat