Stop rebuilding your database for CI and local development

Snapshot once. Branch in seconds. Run tests and coding agents against isolated PostgreSQL, MySQL or MongoDB databases.
Free, no sign-up required.

$ curl -fsSL https://dl.baseshift.com/brancher/install.sh | bash
Using an agent?brancher help agent

Use Cases

One snapshot. Three ways to use it.

Cache the state you want to reuse. Clone the state you want to throw away.

01 · CI

Stop rerunning migrations

Snapshot your database once, after migrations and seed data. Every later CI job clones that prepared state in seconds instead of rebuilding it.

1:58→0:02test setup on a real Django CI job
ci pipeline

02 · Tests

A database for every test worker

Clone the same snapshot once per worker. Run tests in parallel against isolated databases without rebuilding or copying the full database.

03 · Agents

A database branch for every code branch

Each worktree or coding agent branches from the same snapshot. Commit to move main, rebase to catch up, or throw it away.

Built for disposable environments

Reset instantly

Start a fresh clone from the same snapshot after every run.

Share snapshots

Snapshots are files. Hand the exact state to another job, machine or agent.

Throw it away

Clones are disposable. Create one for a job, stop it when the job is done.

Example

Three agents, three worktrees,
one database history.

Every agent rebuilds its own database.

  • Each worktree reruns every migration from scratch. That takes minutes.
  • One agent's migration never reaches the others, so databases drift.
  • Catching up means dump and restore, or rebuilding again.

One snapshot history, a branch per agent.

  • Agents branch from an already-migrated snapshot in seconds.
  • Commit a branch and it becomes the new main.
  • Other agents rebase. New agents start with nothing to rerun.

1/6

sharedstate
Agent 1worktree-a
Agent 2worktree-b
Agent 3worktree-c
nothing shared, every database is a separate copy
db-a · postgres
+ 042

db-b · postgres
042 missing042+ 043

db-c · postgres

new db: running 001 to 042 from scratch · minutes

v1
v2
v1 + 042
+ 042
042 ✓+ 043
cloned from v2 · ready in seconds
042 ✓0 migrations to run

Quickstart

Root defaults to .brancher in the current directory.

Django

Using Django? There's a shorter setup. Install the package, create the clones with one command, then run your tests as usual.

Django setup ↓
01

Install

Supported on Debian Linux and macOS. Use curl on Debian, or curl or Homebrew on macOS. Other Linux distributions and Windows are on the roadmap.

$ curl -fsSL https://dl.baseshift.com/brancher/install.sh | bash
02

Accept the EULA

Recorded once under ~/.config/brancher/eula. Later commands don't prompt.

$ mkdir -p ~/brancher-demo && cd ~/brancher-demo
$ brancher --eula accept version
03

Start an empty Postgres

Defaults: engine postgres, compression zstd, encryption on. The snap key is written to ~/.config/brancher/keys/<root-id>. base and main point at the empty database.

$ brancher init
04

Create a table on main

branch runs the command against a fork of the ref. A clean exit publishes the snapshot and moves the ref. psql picks up PGHOST, PGPORT etc. from the environment brancher sets; no password.

$ brancher branch main -- \
    psql -c "create table items (id int primary key, name text);
             insert into items values (1, 'seed');"
$ brancher ls   # ref · snap id · label · depth
05

Branch

main still has only the seed row. feature has both.

$ brancher branch feature --from main -- \
    psql -c "insert into items values (2, 'feature');"
$ brancher ls
06

Clone

Each line is session id, port and URL. A main clone returns the seed row; a feature clone returns both. Writes in a clone stay in that clone.

$ brancher clone main --count 1
$ brancher clone feature --count 2
<id>  <port>  postgres://postgres@127.0.0.1:<port>/postgres?sslmode=disable

$ psql "postgres://postgres@127.0.0.1:<port>/postgres?sslmode=disable" \
    -c "select * from items;"
07

Shut down

Stops the running clones. brancher ls still lists main and feature.

$ brancher stop --all

Framework integrations

Django tests on an already-migrated database.

DjangoMore frameworks coming

On a large Django project, a lot of test time goes to creating the test database and replaying every migration. The django-baseshift-brancher package skips both. Each test worker gets its own Postgres clone, already migrated to the schema of your current git checkout.

Works with pytest-django (-n N) and manage.py test (--parallel N)

No changes to settings.py

Migrated snapshots are cached per migration commit and shared across branches

Python3.8 to 3.13
Django3.2, 4.2, 5.0 to 6.0
DatabasePostgreSQL
Also needsbrancher installed, and a git repository
run from the folder with manage.py
01
Install the package
$ pip install "django-baseshift-brancher[pytest]"

Leave off [pytest] if you already use pytest-django or run manage.py test. Needs brancher on your PATH.

02
Create one clone per test worker
$ export DJANGO_SETTINGS_MODULE=yourproject.settings
$ unset BASESHIFT_BRANCHES_FILE DATABASE_URL PGHOST PGPORT
$ django-baseshift-brancher clone --count 4

Details are written to .brancher/clones.json. Re-run after checking out different migrations.

03
Run the tests
$ export BASESHIFT_BRANCHES_FILE="$PWD/.brancher/clones.json"

Export it in the same shell that runs the tests.

with pytest

$ pytest -n 4

The plugin loads itself and turns on --reuse-db and --no-migrations. Don't pass --create-db.

or with manage.py test

$ python manage.py test \
    --testrunner django_baseshift_brancher.DiscoverRunner \
    --parallel 4
04
Clean up
$ brancher stop --all

Stops every clone.

Snapshots follow your migration history

add migrations

Builds on the previous snapshot. Branches that split off the same migration commit share it.

edit or delete migrations

Starts over from an empty snapshot, because the new schema can't be built on top of the old one.

rebase

Gets a new snapshot on top of its new parent. Branches from before the rebase keep their own chain.

Using an agent? The README has the exact command sequence and rules for agents.

Full README →
How it works

Block-level copy-on-write under an unmodified database.

brancher uses Baseshift's libc interposition library for block-level copy-on-write. Data is stored in chunks, and metadata describing the state of the file system is stored in .snap files saved when the database shuts down.

your database processYour databasepostgres · mysqld · mongodunmodified binaryfile I/Olibc interpositionBaseshift core · block-level copy-on-writeno code, config or file-system changesChunksdata blocks · zstdonly changed blocks are new.snapfile-system state metadatawritten when the database shuts down.brancher/ on diskyour database processYour databasepostgres · mysqld · mongodunmodified binaryfile I/Olibc interpositionBaseshift coreblock-level copy-on-writeno code, config or file-system changesChunksdata blocks · zstdonly changed blocks are new.snapfile-system state metadatawritten when the database shuts down.brancher/ on disk

Platforms

Debian Linux and macOS. Other Linux distributions and Windows are on the roadmap.

Engines

Postgres, MySQL, MongoDB. More to come.

Storage

zstd compression and encryption on by default. Keys in ~/.config/brancher/keys.

Portability

Snapshots are just files. Move them anywhere files go.

Need prod data? Check out Baseshift.

brancher is built on Baseshift core.

baseshift.com →