← Todos os textos

Cada worktree ganha o próprio banco de dados

Hoje faço quase todo o meu trabalho em git worktrees. Tanto o código com agentes quanto o desenvolvimento de funcionalidades de verdade acontecem num worktree, para que o que eu estiver fazendo fique isolado dos outros fluxos de trabalho. Gosto desse fluxo porque posso estar no meio de uma coisa, largar e ir para outra sem pisar no que deixei aberto ao lado.

Quem diria que os worktrees (um recurso que ignorei no git help por uma década) virariam a tecnologia matadora de 2026.

Se você não conhece os worktrees, dá para aprender sobre eles aqui.

Só tem um problema. Worktrees clonam o seu código. Não clonam nada que não esteja no git, e há duas coisas assim de que você precisa: os arquivos no gitignore e um banco de dados. Então todo worktree que você cria se conecta, todo contente, ao mesmo Postgres local. No instante em que uma branch roda uma migração, ela muda o schema de que as outras três dependem, e lá se vai o meu isolamento perfeito.

Então escrevi uma ferramenta pequena para resolver isso: o wtdb.

Minha configuração é assim:

  • main-repo/: sempre acompanhando origin/main, com migrações rodando depois de cada pull. A cópia de referência limpa.
  • main-repo-worktree-feat-blah-blah/: um worktree de uma branch de feature com banco próprio, além de cache e node_modules copiados do repositório principal.
  • main-repo-worktree-feat-foo-bar/: outro worktree de branch de feature com banco próprio, além de cache e node_modules copiados do repositório principal.

Quando adiciono um worktree, o wtdb se engancha no post-checkout do git e faz as três coisas chatas que ninguém configura na mão:

  1. Clona o banco de dados. Usa o CREATE DATABASE ... TEMPLATE do Postgres, então é uma cópia quase instantânea dos seus dados de desenvolvimento, não um dump e restore em que você vai tomar um café enquanto espera.
  2. Copia o seu arquivo env e reescreve a URL do banco para apontar para a nova cópia.
  3. Copia os arquivos do gitignore de que você realmente precisa. Isso quer dizer node_modules e companhia, com clones copy-on-write, então não gasta espaço em disco.

Agora posso rodar um servidor de desenvolvimento em qualquer worktree e deixar um agente rodar as migrações e mudanças de schema que quiser no sandbox dele.

Para começar, é uma instalação e três comandos:

# Always check the source code of a new tool before 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

A configuração é pequena. É um arquivo .wtdb.json na raiz do seu repositório.

{
  "envFile": ".dev.vars",
  "dbEnvVar": "DATABASE_URL",
  "pathsToCopy": ["node_modules", ".next"]
}

pathsToCopy é qualquer coisa do gitignore de que o seu worktree precise para rodar. O .next aqui pressupõe Next.js, troque pelo cache de build do seu projeto.

Também existe o wtdb status, para ver qual worktree é dono de qual banco, e o wtdb prune, para descartar os órfãos depois de apagar um worktree. Eu gostaria que o git ganhasse algum tipo de hook de worktree para eu nem precisar do wtdb prune.

Por enquanto só existe um adaptador de Postgres, porque é o que eu uso. A camada de banco é uma interface simples (Copy e Drop), então se você usa outro banco, adicionar um adaptador leva uns minutos. PRs são bem-vindos.

Github: willhackett/wtdb.