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 acompanhandoorigin/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:
- Clona o banco de dados. Usa o
CREATE DATABASE ... TEMPLATEdo 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. - Copia o seu arquivo env e reescreve a URL do banco para apontar para a nova cópia.
- Copia os arquivos do gitignore de que você realmente precisa. Isso quer dizer
node_modulese 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.