Use cases

Database per branch, no shared state

Two worktrees. Same myapp_dev database. One runs a migration, the other’s schema breaks. Treeline can give every worktree its own database — cloned from a template in seconds, seeded from hooks, or copied as a SQLite file. Database isolation is opt-in: omit the database block entirely if your project doesn’t need it.

Option A: Clone from a template (PostgreSQL)

PostgreSQL’s createdb --template copies the full schema and data from an existing database without running migrations or seeds. If your template database is ready to go, a new worktree gets a complete database in seconds — even if your seed file takes 20 minutes.

The trick: keep your template database up to date. If you maintain a clean, seeded template (e.g. after each migration, re-seed the template), every clone starts from a known-good state. Your CI can do this, or a post_setup hook on the main worktree can keep it fresh.

.treeline.yml
project: myapp

database:
  adapter: postgresql
  template: myapp_development
  pattern: "{template}_{worktree}"

env:
  PORT: "{port}"
  DATABASE_URL: "postgresql://localhost:5432/{database}"
what happens

$ gtl new feature-auth

Creating worktree feature-auth

Allocated port 3012

Cloned database myapp_development_feature_auth

Wrote .env.local

==> https://myapp-feature-auth.prt.dev

The {database} token in the env block resolves to the cloned database name. The pattern field controls the naming: myapp_development_feature_auth in this example. The template database is never modified.

Managing worktree databases

# Print the worktree’s database name

$ gtl db name

myapp_development_feature_auth

# Drop and re-clone from the template

$ gtl db reset

# Clone from a different source instead

$ gtl db reset --from staging_snapshot

# Restore from a pg_dump file (auto-detects format)

$ gtl db restore dump.sql

# Clean up when done

$ gtl release --drop-db

Option B: Seed from hooks (no template)

If your team prefers running migrations + seeds on every new worktree instead of maintaining a template, skip the database block and use commands.setup to create the database from scratch.

.treeline.yml
project: myapp

env:
  PORT: "{port}"
  DATABASE_NAME: "myapp_dev_{worktree}"

commands:
  setup:
    - bin/rails db:create
    - bin/rails db:schema:load
    - bin/rails db:seed

This approach trades setup speed for simplicity — no template to maintain, every worktree starts from the current schema. If your seed file is slow (10+ minutes), consider Option A instead. If it’s fast or you’re using a framework like Prisma that handles migrations differently, this may be all you need.

You can also combine the two: clone from a template for the schema, then run lightweight data patches in commands.setup.

Option C: SQLite (file copy)

SQLite databases are files. Treeline clones by copying the file to the worktree directory. No server, no createdb.

.treeline.yml
project: myapp

database:
  adapter: sqlite
  template: db/development.sqlite3

Port-dependent data

If your database stores URLs that include the port — OAuth redirect URIs, webhook endpoints, asset URLs — the cloned data will have stale values pointing to the template’s port. Use commands.setup to patch them after cloning:

.treeline.yml
commands:
  setup:
    - psql $DATABASE_URL -c "UPDATE settings SET base_url = 'http://localhost:$PORT'"

Setup commands run after the env file is written, so $PORT and $DATABASE_URL are already available.

When to use which

Approach Speed Best when
Clone from template Seconds Seed is slow, team maintains a clean template database
Seed from hooks Varies Seed is fast, or team uses migrations (Prisma, Knex) instead of templates
SQLite file copy Instant App uses SQLite — no server needed
No database config App doesn’t use a local database, or databases are managed externally

Read next

All use cases