Git Worktrees como Primitivo de Orquestração: 5 Agentes em Paralelo no Mesmo Repo sem Conflito
Worktrees git resolvem um problema que nenhuma plataforma de orquestração menciona: como rodar múltiplos agentes de codificação no mesmo repositório sem que eles sobrescrevam o trabalho uns dos outros. Tutorial completo com aliases bash.
Fabiano Brito
CTO, Autenticare
git worktree permite que N agentes trabalhem no mesmo repositório em paralelo, cada um em seu próprio branch e diretório de trabalho, sem conflitos de estado de arquivo. É o primitivo de orquestração que estava escondido no seu git. Tutorial com aliases bash e padrão de limpeza automática inclusos.
O problema clássico de rodar múltiplos agentes de codificação em paralelo não é de compute — é de estado de arquivo. Quando você lança 5 agentes simultâneos num mesmo repositório com git checkout, eles brigam pelo mesmo índice git, pelas mesmas branches, pelo mesmo diretório de trabalho. O resultado é um estado indeterminado que nenhum dos dois consegue resolver de forma confiável.
A solução existe há anos no git e a maioria dos engenheiros nunca usou em produção: git worktree.
Addy Osmani documentou esse padrão no contexto de agentes de codificação. Este post vai além do tutorial básico e cobre o que faz diferença em produção: gestão de recursos, limpeza automática, e os aliases que tornam o workflow fluido.
O que é um worktree, tecnicamente
Um worktree é um diretório de trabalho separado vinculado ao mesmo repositório git. Cada worktree:
- Tem seu próprio working tree (arquivos em disco)
- Está num branch diferente (obrigatório — dois worktrees não podem estar no mesmo branch)
- Compartilha o mesmo
.git/objects(commits, histórico, refs) - É invisível para os outros worktrees durante a execução
Isso significa que cada agente tem isolamento completo de estado de arquivo, mas acesso ao mesmo histórico compartilhado. Quando termina, faz push da branch e abre PR — igual a qualquer desenvolvedor humano.
# Estrutura com 3 worktrees ativos
$ git worktree list
/Users/dev/meu-repo abc1234 [main]
/Users/dev/meu-repo-feat-a def5678 [auto/feat-a]
/Users/dev/meu-repo-feat-b ghi9012 [auto/feat-b]
/Users/dev/meu-repo-hotfix jkl3456 [auto/hotfix-login]
Cada linha é um diretório separado, cada um rodando um agente diferente, sem nenhuma interferência.
Por que isso importa para orquestração de agentes
O padrão convencional de orquestrar agentes de codificação usa uma das abordagens:
- Um repositório por agente — alto overhead, dificulta compartilhar código base
- Branches isoladas no mesmo repo, com clone — funciona, mas duplica o
.git/objectse é lento - Agentes sequenciais — elimina o paralelismo que você quer
Worktrees são a quarta opção: paralelo, mesmo repo, sem duplicação, sem conflito.
O overhead de criar um worktree é mínimo — é essencialmente criar um diretório com um HEAD apontando para uma nova branch. Nenhuma cópia de objetos git. A startup de um novo agente em worktree leva segundos, não minutos.
Worktrees transformam o git de sistema de controle de versão em sistema de isolamento de contexto para agentes. Você não está rodando vários checkouts — está rodando vários agentes num mesmo repo com segurança de estado.
Setup: aliases bash para workflow fluido
Adicione ao seu ~/.bashrc ou ~/.zshrc:
# Criar worktree para um agente (convenção de nome automática)
wt-agent() {
local REPO_ROOT
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
if [[ -z "$REPO_ROOT" ]]; then
echo "Não está dentro de um repositório git." >&2
return 1
fi
local TASK="${1:?Uso: wt-agent <nome-da-tarefa>}"
local BRANCH="auto/${TASK}"
local WORKTREE="${REPO_ROOT%/*}/$(basename "$REPO_ROOT")-${TASK}"
git -C "$REPO_ROOT" worktree add "$WORKTREE" -b "$BRANCH"
echo "Worktree criado: $WORKTREE (branch: $BRANCH)"
echo "cd $WORKTREE"
}
# Listar worktrees ativos com status resumido
wt-list() {
git worktree list --porcelain | awk '
/^worktree / { wt=$2 }
/^branch / { br=$2 }
/^HEAD / { hd=substr($2,1,7) }
/^$/ { printf "%-50s %-30s %s\n", wt, br, hd }
'
}
# Remover worktree e apagar branch local após merge
wt-clean() {
local TASK="${1:?Uso: wt-clean <nome-da-tarefa>}"
local REPO_ROOT
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
local WORKTREE="${REPO_ROOT%/*}/$(basename "$REPO_ROOT")-${TASK}"
local BRANCH="auto/${TASK}"
git worktree remove "$WORKTREE" --force
git branch -d "$BRANCH" 2>/dev/null || echo "Branch $BRANCH não encontrada localmente (já deletada ou nunca existiu)"
echo "Worktree e branch removidos: $TASK"
}
# Lançar agente Claude Code num worktree (requer claude CLI)
wt-claude() {
local TASK="${1:?Uso: wt-claude <nome-da-tarefa> [prompt]}"
local PROMPT="${2:-}"
local REPO_ROOT
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
local WORKTREE="${REPO_ROOT%/*}/$(basename "$REPO_ROOT")-${TASK}"
if [[ ! -d "$WORKTREE" ]]; then
wt-agent "$TASK"
fi
if [[ -n "$PROMPT" ]]; then
claude --cwd "$WORKTREE" --print "$PROMPT" &
echo "Agente lançado em background (PID: $!)"
else
claude --cwd "$WORKTREE"
fi
}
Com esses aliases, o workflow para lançar 5 agentes paralelos fica assim:
# Terminal 1 — agente de refactoring
wt-claude "refactor-auth" "Refatora o módulo de autenticação para usar o novo JWT provider"
# Terminal 2 — agente de testes
wt-claude "add-tests-payment" "Escreve testes unitários para todos os handlers do módulo de pagamento"
# Terminal 3 — agente de docs
wt-claude "update-api-docs" "Atualiza a documentação da API com os novos endpoints adicionados em #123"
# Terminal 4 — agente de bug fix
wt-claude "fix-session-leak" "Corrige o memory leak na gestão de sessões (issue #456)"
# Terminal 5 — agente de migração
wt-claude "migrate-db-schema" "Escreve migration para adicionar índice composto na tabela de eventos"
Cada comando lança um agente em background, num worktree isolado, numa branch separada. Você acompanha via wt-list.
Padrão de coordenação: o agente orquestrador
Para tarefas dependentes entre si, use um agente orquestrador que despacha subtarefas para agentes worker via worktrees:
#!/usr/bin/env bash
# orchestrate.sh — Exemplo de orquestrador simples
REPO_ROOT=$(git rev-parse --show-toplevel)
TASKS=("fix-auth-bug" "add-auth-tests" "update-auth-docs")
PIDS=()
# Lançar agentes em paralelo
for TASK in "${TASKS[@]}"; do
WORKTREE="${REPO_ROOT%/*}/$(basename "$REPO_ROOT")-${TASK}"
git worktree add "$WORKTREE" -b "auto/${TASK}" 2>/dev/null
claude --cwd "$WORKTREE" --print \
"Sua tarefa: ${TASK}. Ao terminar, faça commit e push da branch auto/${TASK}." \
&
PIDS+=($!)
echo "Agente ${TASK} lançado (PID: ${PIDS[-1]})"
done
# Aguardar todos terminarem
for PID in "${PIDS[@]}"; do
wait "$PID" && echo "Agente $PID concluído" || echo "Agente $PID falhou"
done
echo "Todos os agentes concluídos. Abra os PRs:"
for TASK in "${TASKS[@]}"; do
gh pr create \
--head "auto/${TASK}" \
--title "auto: ${TASK}" \
--body "Gerado por orchestrate.sh" \
2>/dev/null || echo "PR para ${TASK} já existe ou falhou"
done
O ponto crítico aqui é a separação de responsabilidades: o orquestrador apenas despacha e aguarda. Cada worker tem autonomia total dentro do seu worktree.
Limites e cuidados
Worktrees resolvem o problema de estado de arquivo, mas não eliminam todos os conflitos de coordenação:
O que worktrees NÃO resolvem:
- Dois agentes editando o mesmo arquivo em branches diferentes ainda geram conflito de merge no PR — worktrees isolam o working tree, não a intenção de mudança.
- Locks de banco de dados ou recursos externos (ex: um agente que roda migrations enquanto outro testa contra o mesmo banco de dev) precisam de coordenação externa.
- Limites de worktrees simultâneos dependem do filesystem — em NFS ou volumes lentos, cada worktree adicional tem custo real de I/O.
Boas práticas:
# Antes de criar worktrees, definir particionamento explícito de arquivos
# Agente A: src/auth/**
# Agente B: src/payment/**
# Agente C: src/notifications/**
# → sem sobreposição → sem conflito de merge
A decomposição de tarefas com particionamento explícito de arquivos reduz conflitos de merge a zero na maioria dos casos.
Limpeza automática pós-merge
Deixar worktrees esquecidos acumula diretórios órfãos. Configure um hook pós-merge no repositório principal:
# .git/hooks/post-merge (ou via script de CI)
#!/usr/bin/env bash
# Remove worktrees de branches que foram mergeadas
MERGED_BRANCHES=$(git branch --merged main | grep "auto/" | tr -d ' ')
for BRANCH in $MERGED_BRANCHES; do
TASK="${BRANCH#auto/}"
REPO_ROOT=$(git rev-parse --show-toplevel)
WORKTREE="${REPO_ROOT%/*}/$(basename "$REPO_ROOT")-${TASK}"
if [[ -d "$WORKTREE" ]]; then
git worktree remove "$WORKTREE" --force
echo "Worktree removido: $WORKTREE"
fi
git branch -d "$BRANCH"
done
Implementando orquestração de agentes no seu repositório?
A Autenticare projeta arquiteturas multi-agente com isolamento de contexto, coordenação de branches e integração com pipelines de CI/CD. Converse com nosso time.
Posts relacionados
Orquestra de agentes: multi-agent em produção sem virar caos
Engenharia AgênticaQuando NÃO usar agentes autônomos: 4 contraindicações que vimos quebrarem em produção
Fontes primárias: git-worktree — documentação oficial · Addy Osmani — Code Agent Orchestra
