Todos os Artigos

Git Worktrees: Um Guia Prático com Lazygit e Yazi

GitTutorialDevTools
Git Worktrees: Um Guia Prático com Lazygit e Yazi

O que são Git Worktrees?

Git worktrees permitem que você tenha múltiplas branches checked out simultaneamente em diretórios diferentes. Em vez de fazer stash ou commit de trabalho em progresso para trocar de branch, você simplesmente usa cd para outro diretório.

Com um workflow git normal, seu repositório pode ter apenas uma branch checked out por vez. Com worktrees, cada branch vive em seu próprio diretório, mas todos compartilham o mesmo histórico git. Commits, stashes e remotes são compartilhados entre todos os worktrees.

Duas Abordagens para Worktrees

Abordagem A: Adicionar Worktrees a um Repo Existente

Você mantém seu clone atual e adiciona worktrees ao lado. Rápido para começar, mas o worktree principal é um clone regular com uma pasta .git, tornando-o estruturalmente diferente dos outros.

Abordagem B: Bare Clone + Worktrees (Recomendado)

Você cria um bare clone (sem diretório de trabalho) e depois adiciona worktrees para cada branch, incluindo a principal. Este é o workflow adequado: todas as branches são iguais, e o bare repo é apenas um banco de dados git compartilhado.

Usamos a Abordagem B porque ela oferece uma estrutura limpa e simétrica onde nenhuma branch é especial.

Configurando um Bare Clone

Passo 1: Criar o Bare Clone

A pasta wrapper substitui seu clone regular, então use o mesmo nome do projeto que você sempre usou:

cd ~/Work/my-org
mv my-project my-project-old

mkdir my-project
cd my-project
git clone --bare <repo-url> .bare

Você pode ficar tentado a adicionar um sufixo como -wt ou .git para distinguir de um clone regular. Não faça isso. Uma vez que você adota worktrees, este é seu repo. Um sufixo é apenas ruído que você vai digitar todos os dias.

Passo 2: Configurar o Ponteiro .git

echo "gitdir: ./.bare" > .git

Isso cria um arquivo .git (não diretório) que diz ao git que o repo real está em .bare. Comandos git agora funcionam a partir da pasta wrapper.

Passo 3: Configurar Refs de Fetch Remoto

Por padrão, um bare clone não busca refs de branches remotas corretamente. Corrija isso:

git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"

Passo 4: Buscar Tudo

git fetch origin

Agora você tem o histórico completo do repo e pode criar worktrees.

Criando e Gerenciando Worktrees

Crie seu primeiro worktree para a branch principal:

git worktree add main

Isso cria um diretório main/ com a branch checked out. Para branches de feature:

# Branch existente
git worktree add feature-branch

# Nova branch
git worktree add -b my-new-feature my-new-feature

Para listar, remover e limpar:

# Listar todos os worktrees
git worktree list

# Remover um worktree (mantém a branch)
git worktree remove feature-branch

# Deletar a branch também
git branch -d feature-branch

# Limpar referências obsoletas
git worktree prune

A Estrutura de Diretórios

Após a configuração, seu projeto fica assim:

my-project/                  # Wrapper (você não trabalha aqui diretamente)
├── .bare/                   # Banco de dados git (compartilhado por todos)
├── .git                     # Arquivo apontando para .bare
├── .shared/                 # Arquivos gitignored com symlinks nos worktrees
│   └── .env
├── new-worktree.sh          # Script auxiliar
├── main/                    # Worktree: branch principal (manter limpo)
│   ├── .env -> ../.shared/.env
│   ├── src/
│   └── package.json
└── feature-branch/          # Worktree: branch de feature (trabalhar aqui)
    ├── .env -> ../.shared/.env
    ├── src/
    └── package.json

Cada worktree tem seus próprios node_modules, saída de build e estado de trabalho. São diretórios completamente independentes. Você precisa executar npm install em cada um.

Integração com Lazygit

Lazygit tem suporte nativo a worktrees. Abra-o de qualquer diretório de worktree e ele detecta a configuração automaticamente.

Encontrando o Painel de Worktrees

A aba Worktrees fica dentro do painel de Branches:

  1. Pressione 3 para abrir o painel de Branches
  2. Alterne sub-abas com ] (próximo) e [ (anterior): Branches Locais → Remotes → Tags → Worktrees

Observe que a tecla w é dependente do contexto: no painel Files ela faz commit de arquivos staged, no painel Branches ela cria um worktree da branch selecionada. Ela não abre um painel de worktrees.

Ações de Worktree

Na aba Worktrees:

  • Enter — Mudar para o worktree selecionado
  • n — Criar novo worktree
  • d — Remover o worktree selecionado
  • ? — Mostrar todos os atalhos (funciona em qualquer painel)

Diffs Lado a Lado com Delta

Lazygit não tem uma visualização de diff dividida nativa, mas você pode obter diffs lado a lado usando o delta como pager personalizado:

brew install git-delta

Então crie a configuração do lazygit (macOS: ~/Library/Application Support/lazygit/config.yml, Linux: ~/.config/lazygit/config.yml):

git:
  paging:
    colorArg: always
    pager: delta --dark --paging=never --side-by-side

Todos os diffs no lazygit agora serão exibidos lado a lado com destaque de sintaxe. Pressione e em qualquer visualização de diff para abrir o arquivo no seu $EDITOR.

Layouts de Teclado Não-US

As teclas [ e ] para alternar abas podem ser difíceis de acessar em teclados não-US:

  • Alemão Mac: [ = Option+5, ] = Option+6
  • Alemão Windows/Linux: [ = AltGr+8, ] = AltGr+9

Integração com Yazi

Yazi é um gerenciador de arquivos de terminal que combina bem com worktrees. Como todas as branches são diretórios irmãos, você pode navegar entre eles visualmente.

# Abrir yazi na pasta wrapper
cd my-project
yazi

Workflow Baseado em Abas

A configuração recomendada é uma aba do yazi por worktree ativo:

  1. Abra o yazi na pasta wrapper
  2. Entre em main/ → pressione t para abrir em nova aba
  3. Volte com h, entre em feature-x/ → pressione t novamente
  4. Alterne entre abas com 1 e 2
  5. Feche uma aba com Ctrl+c

Executando Comandos pelo Yazi

  • ; — Executar comando em segundo plano (não bloqueante, ideal para npm start)
  • : — Executar comando em primeiro plano (bloqueante, ideal para npm install)
  • w — Abrir gerenciador de tarefas (ver tarefas em segundo plano)
  • Enter (no gerenciador) — Ver logs da tarefa
  • x (no gerenciador) — Cancelar uma tarefa
  • q (no gerenciador) — Voltar ao yazi

Isso significa que você pode iniciar um servidor de desenvolvimento com ;, digitar npm start, e continuar navegando pelos arquivos enquanto ele roda.

Gerenciando Arquivos Gitignored entre Worktrees

Um detalhe crítico que pega muitos de surpresa: Arquivos gitignored não são compartilhados entre worktrees. Cada worktree é seu próprio diretório no disco. Arquivos como .env, configurações de IDE ou configurações de ferramentas existem apenas no worktree onde foram criados.

A Solução com Symlinks

Mantenha arquivos gitignored compartilhados em um diretório .shared/ na pasta wrapper e crie symlinks para cada worktree:

mkdir .shared
cp main/.env .shared/.env

# Criar symlinks nos worktrees existentes
ln -s "$(pwd)/.shared/.env" main/.env
ln -s "$(pwd)/.shared/.env" feature-branch/.env

Uma única fonte de verdade, e todos os worktrees veem o mesmo arquivo. Editar em um worktree muda em todos, pois todos apontam para o mesmo local.

Compartilhar: Configuração e ferramentas (.env, .editorconfig, configurações). Manter separado: Arquivos gerados (node_modules, dist, caches de build).

A Armadilha da Barra Final

Se seu .gitignore usa uma barra final para ignorar diretórios:

.myconfig/

Isso não vai corresponder a symlinks para diretórios. O git trata symlinks como arquivos, então .myconfig/ só corresponde a um diretório real. O symlink aparece como untracked.

Solução: remova a barra final:

.myconfig

Isso corresponde a diretórios, arquivos e symlinks. Revise seu gitignore global e remova barras finais de padrões que possam ser symlinked.

Automatização com um Script Auxiliar

Criar symlinks manualmente fica tedioso. Coloque um script auxiliar na pasta wrapper:

#!/usr/bin/env bash
set -euo pipefail

if [ $# -eq 0 ] || [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
  echo "Usage: ./new-worktree.sh <branch-name> [--new]"
  echo ""
  echo "  <branch-name>        Checkout de branch existente"
  echo "  <branch-name> --new  Criar nova branch e worktree"
  echo ""
  echo "Todos os arquivos em .shared/ são symlinked nos novos worktrees."
  exit 0
fi

BRANCH_NAME="$1"
CREATE_NEW="${2:-}"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SHARED_DIR="$SCRIPT_DIR/.shared"
WORKTREE_DIR="$SCRIPT_DIR/$BRANCH_NAME"

if [ "$CREATE_NEW" = "--new" ]; then
  git worktree add -b "$BRANCH_NAME" "$WORKTREE_DIR"
else
  git worktree add "$WORKTREE_DIR" "$BRANCH_NAME"
fi

if [ -d "$SHARED_DIR" ]; then
  for item in "$SHARED_DIR"/.[!.]* "$SHARED_DIR"/*; do
    [ -e "$item" ] || continue
    name="$(basename "$item")"
    target="$WORKTREE_DIR/$name"
    if [ ! -e "$target" ]; then
      ln -s "$item" "$target"
      echo "  Linked: $name"
    else
      echo "  Skipped (exists): $name"
    fi
  done
fi

echo "Worktree ready: $WORKTREE_DIR"

Agora cada novo worktree automaticamente recebe todos os arquivos compartilhados via symlink.

Workflow Diário

Mantenha seu worktree principal limpo como baseline estável. Trabalhe nos worktrees de feature:

main/              ← manter limpo, pull aqui, criar branches daqui
feature/something/ ← trabalhar aqui de verdade
feature/other/     ← outro trabalho aqui

Iniciando uma Nova Feature

./new-worktree.sh feature/my-feature --new
cd feature/my-feature
npm install
npm start

Trocando de Contexto

Sem stash, sem commit de WIP. Apenas:

# Terminal
cd ../main

# Lazygit: Painel Branches (3) → Aba Worktrees (]) → Enter
# Yazi: navegar para o diretório irmão

Code Review

git fetch origin
git worktree add pr-review origin/someones-branch
cd pr-review
npm install && npm start
# Revisar, testar, pronto
git worktree remove pr-review

Dicas e Armadilhas

  • Regra de mesma branch: Você não pode ter dois worktrees na mesma branch.
  • Estado git compartilhado: Commits e stashes são compartilhados. Um commit em um worktree é visível de todos os outros.
  • Dependências separadas: Cada worktree precisa de seu próprio npm install.
  • Tratamento de IDE: Abra sua IDE em pastas de worktree individuais, não no wrapper. VS Code lida bem com o arquivo .git; outras IDEs podem precisar de configuração.
  • Limpeza: Remova worktrees que você não precisa mais. Execute git worktree prune periodicamente para limpar referências obsoletas.

Quer saber mais?

Vamos discutir como essas tecnologias podem ajudar seu negócio.