berry is a single-script bash-only Postgres branch manager with a small TUI powered by gum.
When working on a feature branch, it's likely migrations on that branch wouldn't be needed on the other branches (or at least the main branch) yet. berry allows to create copies (aka branches) of the main dev db and build from there so you don't have to recreate and re-seed the db every time.
Install berry from GitHub:
curl -fsSL https://raw.githubusercontent.com/blackmann/pgdb/main/install.sh | bashberry listshows databases on the current Postgres instanceberry branchlets you choose a source database, pick an existing branch or create a new one, then prints the URL to useberry deletelets you choose a branch database and remove it with confirmationberry url <database>prints a Postgres URL for any database
Branch databases follow this naming convention:
<source_db>__<branch_name>
Example:
app__feature_login
bashpsqlgumfor interactive commands
Install gum on macOS with:
brew install gumberry accepts an optional base connection URL:
export DBURL=postgresql://postgres:postgres@localhost:5432/appYou can also use DATABASE_URL as a fallback.
If neither is set, berry falls back to whatever psql would use by default on your machine.
List visible databases:
./berry listberry list groups branch databases under their parent with a small tree view and shows database sizes in a right-aligned column.
Sample output:
Databases
◆ adeton 124.00mb
├─ adeton/campaigns 8.00mb
╰─ adeton/plans 22.00mb
◆ otr 1.20gb
◆ ussdk 310.00mb
System
postgres 7.28mb
List branches for one database:
./berry list --branches appSample output:
app/feature_login 8.00mb
app/bugfix_auth 22.00mb
Create or switch to a branch:
./berry branchSample output:
Branch ready: adeton/plans
postgresql://postgres@127.0.0.1:5432/adeton__plans
Delete a branch:
./berry deleteSample output:
Deleted branch: adeton/plans
Print a URL directly:
./berry url app/feature_loginSample output:
postgresql://postgres@127.0.0.1:5432/app__feature_login
berry branchclones databases withCREATE DATABASE ... WITH TEMPLATE ...- source databases must not be template databases
- branch creation is naming-based and stateless in v1
- branch names are shown as
source/branchin the UI, while the real Postgres database name remainssource__branch - when
DBURLis set,berryreuses it as the base for the printed branch URL - when
DBURLis not set,berrytries to infer a fuller URL from the active Postgres connection and falls back topostgresql://localhost/database_name - if the source database is busy,
berrystops and tells you to retry after closing connections