← Back

Every worktree gets its own database

I do almost all my work in git worktrees now. Both agentic coding and my actual feature development is done in a worktree so that whatever. I find this flow useful because I can be working on something, leave it and work on something else without trampling whatever I’ve got open next door.

Who’d have thought worktrees (a feature that I have ignored in git help for a decade) would turn out to be the killer technology of 2026.

If you’re not familiar with worktrees, you can learn about them here.

There’s one problem. Worktrees clone your code. They don’t clone anything that isn’t checked into git, and that’s two things you actually need: your gitignored files, and a database. So every worktree you create cheerfully connects to the exact same local Postgres. The moment one branch runs a migration it’s changed the schema the other three rely on, and there goes my perfect isolation.

So I wrote a small tool to fix it: wtdb.

My setup looks like this:

  • main-repo/ — always tracking origin/main, migrations run after every pull. The clean reference copy.
  • main-repo-worktree-feat-blah-blah/ — a feature branch worktree with its own database and with cache, node_modules copied from the main repo.
  • main-repo-worktree-feat-foo-bar/ — another feature branch worktree with its own database and with cache, node_modules copied from the main repo.

When I add a worktree, wtdb hooks into git’s post-checkout and does the three boring things nobody sets up by hand:

  1. Clones the database. It uses Postgres’ CREATE DATABASE ... TEMPLATE, so it’s a near-instant copy of your dev data — not a dump-and-restore you go and make a coffee during.
  2. Copies your env file and rewrites the database URL to point at the new copy.
  3. Copies the gitignored bits you actually neednode_modules and friends with copy-on-write clones, so it doesn’t cost you disk space.

Now I can run a dev server against any worktree, let an agent run whatever migrations and schema changes it fancies in its own sandbox.

Getting started is one install and three commands:

# Always check the source code of a new tool before just installing it. 
# I know this is a bad practice. I will make this available on homebrew soon. Maybe.
curl -fsSL https://raw.githubusercontent.com/willhackett/wtdb/main/install.sh | sh

wtdb init      # writes a starter .wtdb.json
wtdb install   # installs the post-checkout hook
wtdb sync      # provision the current worktree by hand

The config is small, it’s a .wtdb.json file in your repo root.

{
  "envFile": ".dev.vars",
  "dbEnvVar": "DATABASE_URL",
  "pathsToCopy": ["node_modules", ".next"] // Assuming you use Next.js
}

There’s also wtdb status to see which worktree owns which database, and wtdb prune to drop the orphans after you delete a worktree. I would really like git to add some kind of worktree hooks so that wtdb prune is not needed.

Right now there’s only a Postgres adapter, because that’s what I use. The database layer is a plain interface (Copy and Drop) so if you’re on something else, adding an adapter takes a few minutes. PRs welcome.

Github: willhackett/wtdb.