O congestionamento do checkout único
Estou desenvolvendo um app de menu bar no macOS. Tenho três features no backlog: um sparkline de consumo, notificações nativas, e um widget de desktop. As três são independentes. Vou fazer as três com Claude Code.
O problema: Claude Code trabalha em um diretório. Um diretório tem uma branch. E git checkout é como uma rotatória de uma só faixa: só passa um.
Se quero avançar as três ao mesmo tempo, minhas opções clássicas são:
Pingue-pongue do stash:
git stash, mudar branch, trabalhar,git stash pop, rezar para que não hajam conflitos. Repetir até a loucura ou a aposentadoria, o que vier primeiro.Clonar o repo três vezes: Funciona, mas agora tenho três cópias de
.git/, três históricos independentes, e umgit fetchpara fazer em cada um. Um desperdício.Aceitar a vida serial: Uma feature atrás da outra. Seguro, previsível, e lento como um merge sort na mão.
Nenhuma é legal. Mas há uma quarta opção que está no git desde 2015 e que quase ninguém usa.
Worktrees: a solução que você já tinha instalada
Um worktree é um segundo diretório de trabalho que compartilha o mesmo repositório .git. Sem cópias, sem clones, sem magia negra.
A analogia: seu repo é uma biblioteca. Até agora você tinha uma mesa onde só podia ter um livro aberto. Um worktree é colocar mais mesas. Cada uma com um livro diferente aberto, mas todas pegando da mesma estante.
~/code/meuapp/ ← mesa 1 (main)
.git/ ← a biblioteca (uma só)
~/code/meuapp-sparkline/ ← mesa 2 (feature/sparkline)
.git ← arquivo, não pasta (ponteiro para a biblioteca)
~/code/meuapp-notificacoes/ ← mesa 3 (feature/notifications)
.git ← outro ponteiro
Cada diretório é um checkout completo com todos os arquivos. Você pode compilar em um, rodar testes em outro, e ter seu agente de IA trabalhando no terceiro. Ao mesmo tempo.
Criar é uma linha
Do seu repo principal:
| |
Pronto. Dois diretórios novos, cada um na sua branch, compartilhando todo o banco de dados git. Nada de clonar, nada de configurar remotes, nada de duplicar histórico.
O que compartilham e o que não
Isso é importante. Os worktrees compartilham todo o repo: commits, branches, tags, remotes, hooks, configuração. Se você faz um commit no worktree do sparkline, pode vê-lo imediatamente do de notificações sem fazer fetch nem nada, porque é o mesmo banco de dados.
O que não compartilham:
- Os arquivos no disco (cada mesa tem sua cópia de trabalho)
- A área de staging (cada um tem seu próprio
git add) - O HEAD (cada um aponta para sua branch)
Dito em linguagem simples: o estado de “no que estou trabalhando” é privado de cada worktree. Todo o resto é comum.
O fluxo de trabalho com agentes de codificação
Aqui é onde fica interessante. Com worktrees, você pode ter literalmente vários agentes trabalhando em paralelo no mesmo projeto:
| |
Cada instância do Claude tem seu próprio diretório, sua própria branch, seu próprio .build/. Não se atropelam. Não competem pelo index. Não precisam fazer stash de nada.
E como compartilham o banco de dados git, quando um dos agentes termina e faz push, os demais já veem essa branch.
Fazer merge: exatamente igual que sempre
Os worktrees não mudam nada do fluxo de merge. São branches normais em diretórios separados:
| |
Quando termina, você limpa:
| |
As pegadinhas que ninguém te conta
1. Uma branch, um worktree
Você não pode ter main checada em dois worktrees ao mesmo tempo. É por design: evita que dois diretórios modifiquem o mesmo HEAD e se corrompam. Se precisa de um segundo checkout de main, crie uma branch temporária.
2. O primeiro build é do zero
Cada worktree tem seu próprio diretório de build. A primeira compilação vai ser lenta. Depois, cada worktree mantém seu cache independente, que é justamente a vantagem sobre o git checkout clássico (que invalida o cache toda vez que você muda de branch).
3. Arquivos locais não rastreados
Seu .env.local, configurações de editor, arquivos que não estão no git… não são copiados para o worktree novo. Você terá que recriá-los ou fazer symlinks.
4. Apps com estado compartilhado no disco
Se seu app escreve dados em ~/Library/Application Support/ ou similar, duas instâncias do app de diferentes worktrees vão competir pelo mesmo arquivo. Não é um problema do worktree, é um problema de rodar duas instâncias do mesmo app. A solução: não rodar dois ao mesmo tempo, ou parametrizar o diretório de dados por build.
5. Não apague o diretório na mão
Se você faz rm -rf do worktree em vez de usar git worktree remove, o git continua achando que a branch está ocupada. Execute git worktree prune para limpar as referências órfãs.
6. O remote não sabe de nada
Os worktrees são 100% locais. Gitea, GitHub, GitLab… nenhum remote sabe que existem. Só veem git push normais com branches normais. É como perguntar se seu servidor tem problemas com você usar Vim ou VS Code: não sabe, não afeta.
Boas práticas
Convenção de nomes: coloque os worktrees como irmãos do repo original, com um sufixo descritivo:
~/code/meuapp/ ← main
~/code/meuapp-sparkline/ ← feature
~/code/meuapp-notificacoes/ ← feature
~/code/meuapp-hotfix-login/ ← hotfix
Assim um ls ~/code/meuapp* te mostra tudo de uma só olhada.
Um worktree por feature, não por capricho: crie worktrees para trabalho que realmente vai ser paralelo. Se você vai fazer uma coisa atrás da outra, uma branch normal com checkout é suficiente.
Limpe quando terminar: os worktrees abandonados são como as branches que ninguém apaga — se acumulam e confundem. git worktree list é seu amigo.
Não edite o mesmo arquivo de dois worktrees: tecnicamente você pode, cada um tem sua cópia. Mas se ambos modificarem o mesmo arquivo, você terá conflitos ao fazer merge. Tente fazer com que as features toquem áreas diferentes do código.
Proposta de fluxo de trabalho completo
Para quem quiser um fluxo de trabalho organizado, aqui vai o que eu uso:
| |
O ciclo é: criar → trabalhar em paralelo → push/PR → merge → limpar. Cada worktree vive o que vive a feature, nem mais nem menos.
Para fechar
Os worktrees estão no git desde a versão 2.5 (julho de 2015). Mais de dez anos. E a maioria das pessoas continua fazendo git stash como se estivéssemos em 2010.
Com a chegada dos agentes de codificação, o gargalo não é mais a velocidade com que você escreve código — é a velocidade com que consegue mudar de contexto. E os worktrees eliminam essa mudança de contexto completamente: você não muda de branch, muda de diretório. cd em vez de checkout.
Que é, no fim das contas, o que sempre deveríamos ter feito.
TL;DR: git worktree add ../nome -b branch cria um segundo diretório de trabalho no mesmo repo. Sem cópias, sem stash, sem invalidar caches. Perfeito para ter vários agentes de codificação trabalhando em paralelo. Limpe com git worktree remove quando terminar.