Przejdź do głównej zawartości

git worktrees — jeden filesystem na agenta, bez kolizji

Q15 · Parallelism & automation Jak używasz git worktrees w pracy agentów?

Odpowiedź na maks: “Mam workflow (skrypt/skill/Conductor), który automatycznie tworzy worktree per agent.”

Era pojedynczego checkout-u w AI-codingu skończyła się gdzieś w Q1 2026. W momencie, w którym masz dwa agenty edytujące to samo repo przez więcej niż dziesięć–piętnaście minut na raz, jeden working directory przestaje być realny. Agent A zaczyna refactor src/api/checkout.ts. Agent B, odpalony dwie minuty później w innym terminalu, otwiera ten sam plik ze stale read. Agent B pisze swoje edycje. Agent A ponownie czyta plik, widzi linijki agenta B, gubi się, cofa połowę z nich. Oba agenty commitują. I masz w working tree dwie niedokończone zmiany sklejone przypadkiem — żaden z agentów nie potrafi wyjaśnić, co się stało.

Worktrees rozwiązują problem kolizji plików na warstwie filesystemu, zamiast próbować koordynować to na warstwie promptu. Każdy worktree to osobny katalog na osobnym branchu, wszystkie podpięte do tej samej bazy obiektów .git. Z punktu widzenia agenta to tylko cd ~/work/myrepo-fix-checkout zamiast cd ~/work/myrepo. Z punktu widzenia gita nic nie jest duplikowane — branche i commity są wspólne, różnią się tylko pliki w checkout-cie. Z Twojego punktu widzenia możesz odpalić cztery, sześć, osiem równoległych agentów na tym samym repo i nigdy nie musisz myśleć, który nadpisze edycje drugiego.

Minusem starego patternu “git stash; git checkout drugi-branch; zrób-coś; git checkout z powrotem” było to, że wymuszał seryjną pracę nawet wtedy, gdy zadania były z natury równoległe. Worktrees zdejmują to ograniczenie. Minusem trzymania kilku pełnych checkout-ów na dysku był koszt dysku i wielkość node_modules — ten minus stopniowo zjadły SSD i narzędzia, które dzielą zależności między worktree-ami. Minus, który zostaje i który łapie prawie każdy zespół adoptujący worktrees, to fakt, że runtime nie izoluje się za darmo: dwa agenty na dwóch worktree-ach oba chcą bindować port 3000, oba spodziewają się Postgresa na localhost:5432, oba czytają ten sam .env. To realny problem i wrócimy do niego niżej — ale mniejszy niż kolizje plików, bo przynajmniej wybucha głośno zamiast po cichu psuć diff.

Krótko: worktrees są dziś load-bearing infrastrukturą dla pracy z równoległymi agentami w 2026, w tym samym sensie, w jakim virtualenvy stały się load-bearing dla Pythona w latach 2010-tych. Nie potrzebujesz ich do szybkiego one-off chatu; bezwzględnie potrzebujesz w momencie, w którym idziesz powyżej jednego agenta na raz.

Pełną punktację za Q15 dostajesz tylko wtedy, kiedy wszystkie trzy poniższe są prawdą:

  • Worktree powstaje automatycznie dla każdego równoległego zadania agenta. Kiedy odpalasz agenta numer 2, nie wpisujesz ręcznie git worktree add ../myrepo-feat-X feat-X — robi to za Ciebie narzędzie, skrypt albo skill. Conductor, Claude Squad, Cursor /worktree albo własny ~/.claude/skills/spawn-worktree-agent — wszystkie się kwalifikują. Chodzi o to, że tarcie zniknęło.
  • Cykl życia worktree jest zarządzany, nie porzucany. Kiedy agent kończy (PR zmergowany, branch skasowany, zadanie anulowane), worktree jest sprzątane — albo automatycznie przez to samo narzędzie, albo cotygodniowym git worktree prune. Nie masz jedenastu pół-żywych worktree-ów sprzed trzech miesięcy na laptopie.
  • Per-worktree runtime jest przynajmniej zauważony. Wiesz, że dwa agenty nie mogą równocześnie bindować portu 3000 i coś z tym zrobiłeś — .envrc per worktree, port offsets, Docker Compose project name na podstawie katalogu albo narzędzie do izolacji runtime’u jak amux. “Po prostu nie odpalam równolegle dev serverów” się liczy; “próbowałem i się wywaliło, więc odpuściłem” nie.

Wszystko mniejsze — “wiem co to worktree, ale tworzę je ręcznie raz na tydzień” albo “spróbowałem Conductora raz i się nie przyjęło” — to mid-tier w Q15.

Conductor (zarządzanie worktree-ami dla równoległych agentów)

Dział zatytułowany „Conductor (zarządzanie worktree-ami dla równoległych agentów)”

Conductor od Melty Labs to macOS-owa aplikacja, która przyniosła worktree-per-agent ludziom poza CLI. Orkiestruje równoległe Claude Code i Codex agenty, każdego w izolowanym git worktree, i daje Ci GUI do śledzenia ich — co robi każdy z nich, na jakim branchu siedzi, co zmienił, czy testy przeszły. Model to “jedno zadanie = jeden agent = jeden worktree”, a Conductor obsługuje tworzenie i sprzątanie automatycznie.

Siłą Conductora jest GUI plus fakt, że rozumie cykl życia zadania, nie tylko worktree. Kiedy zadanie się kończy, klikasz przycisk, worktree się rozbiera, branch albo idzie na push, albo do kosza, a slot zwalnia się pod następne. Dla ludzi, którzy nie chcą żyć w terminalu, to najprostszy sposób, żeby trafić w maks na Q15.

Claude Squad to terminalowa, napisana w Go wersja tego samego pomysłu — zarządza wieloma instancjami agentów kodujących AI równocześnie, każdą we własnym worktree. Kiedy odpalasz nowego agenta, Claude Squad tworzy izolowany worktree, przełącza tam nowego agenta i daje Ci tmux-podobne UI do przełączania się między nimi. Działa cross-platform (macOS, Linux, Windows przez WSL) i współpracuje z Claude Code, Codex CLI i innymi agentami kodującymi.

Jeśli już żyjesz w terminalu/tmuxie, Claude Squad to ścieżka najmniejszego oporu. Jest darmowy, open-source, a model jest taki sam jak w Conductorze: każdy nowy agent = nowy worktree, i to jest domyślne zachowanie, nie opt-in.

Cursor 3 (kwiecień 2026) wypuścił Agents Window jako centralny multi-agent interface — odpala agentów równolegle w lokalnych workspace’ach, środowiskach cloud, git worktree-ach i remote SSH. Komenda /worktree odpala git worktree add, żeby stworzyć izolowany working directory na nowym branchu, a potem spawnuje proces agenta przyspawanego do tego katalogu. Każdy agent dostaje swój widok filesystemu, więc edycje nie zderzają się w trakcie. Kiedy agent kończy, robisz review diffa i mergujesz.

Dla użytkowników Cursora to ścieżka najmniejszego oporu: jest już w edytorze, rozumie ten sam indexing i te same rules, które masz skonfigurowane dla głównego checkout-u, a tworzenie worktree to dwa kliknięcia zamiast komendy shellowej.

Prymitywy, które owijają wszystkie te narzędzia, są proste i warto je znać, nawet jeśli nigdy nie odpalisz ich ręcznie:

Okno terminala
# Utwórz nowy worktree na nowym branchu
git worktree add ../myrepo-fix-checkout -b fix/checkout-validation
# Wylistuj wszystkie worktree podpięte do tego repo
git worktree list
# Usuń worktree (kiedy zadanie się skończyło)
git worktree remove ../myrepo-fix-checkout
# Sprzątanie referencji do skasowanych worktree-ów
git worktree prune

Cienki wrapper, który skleja git worktree add ze sprzątaniem, którego potrzebuje Twój projekt, w zupełności wystarcza, żeby trafić w maks na Q15 — nie musisz instalować zewnętrznego narzędzia, jeśli nie chcesz:

~/bin/spawn-agent-worktree
#!/usr/bin/env bash
# usage: spawn-agent-worktree <slug>
set -euo pipefail
slug="$1"
repo_root="$(git rev-parse --show-toplevel)"
repo_name="$(basename "$repo_root")"
parent_dir="$(dirname "$repo_root")"
worktree_dir="$parent_dir/${repo_name}-${slug}"
branch="agent/${slug}"
git worktree add "$worktree_dir" -b "$branch"
# Przenieś lokalne pliki, których agenty potrzebują, a git je ignoruje.
cp "$repo_root/.env" "$worktree_dir/.env" 2>/dev/null || true
cp "$repo_root/.env.local" "$worktree_dir/.env.local" 2>/dev/null || true
# Zainstaluj zależności w nowym worktree, żeby agent miał działający build.
( cd "$worktree_dir" && [ -f package.json ] && npm install --no-audit --no-fund ) || true
echo "$worktree_dir"

Wrzuć to na $PATH, wystaw to Claude Code jako slash command (np. ~/.claude/skills/spawn-worktree-agent/SKILL.md), i masz ten sam efekt co Conductor albo Claude Squad dla 80% przypadków — kosztem jakichś trzydziestu linijek shellu.

Izolacja runtime’u (czego worktrees nie rozwiązują)

Dział zatytułowany „Izolacja runtime’u (czego worktrees nie rozwiązują)”

Worktrees rozwiązują kolizje plików. Nie rozwiązują kolizji portów, kolizji baz danych, kolizji cache’a ani kolizji .env. W momencie, w którym odpalisz npm run dev na dwóch worktree-ach równocześnie i oba spróbują zbindować localhost:3000, drugi odmówi startu. Workflow worktree-owy, który to ignoruje, jest niekompletny.

Patterny fixujące w 2026:

  • Port offsets na podstawie slug-a worktree. Zhashuj nazwę katalogu worktree do port offsetu i zapisz do per-worktree .envrc (albo .env.local). Agent A dostaje port 3001, Agent B port 3007, żaden się nie tłucze z drugim.
  • Docker Compose project name = nazwa katalogu worktree. docker compose -p "$(basename "$PWD")" up trzyma kontenery każdego worktree w osobnym namespace, włącznie z sieciami i wolumenami.
  • Dedykowane narzędzie do izolacji runtime’u. Open-source projekty jak amux istnieją specjalnie po to, żeby położyć izolację portów i procesów na worktree-ach, żeby dwa agenty nie konkurowały o ten sam localhost. Jeśli odpalasz 4+ równoległych agentów, którzy wszyscy potrzebują dev serverów, to przestaje być opcjonalne.

Nie potrzebujesz wyrafinowanego rozwiązania od dnia pierwszego — nawet jednolinijkowy “port offset na bazie basename $PWD” wewnątrz Twojego dev scriptu wystarczy, żeby przejść z “zepsute” na “działa”. Ale musisz mieć coś.

  1. Wybierz, gdzie worktree mieszkają na dysku. Popularny pattern: trzymaj wszystkie worktree dla myrepo jako siblingi — ~/work/myrepo, ~/work/myrepo-feat-x, ~/work/myrepo-fix-y. Unikaj zagnieżdżania worktree wewnątrz głównego checkout-u; narzędzia (indeksery edytora, watchery, instalatory zależności) zwykle się gubią, kiedy node_modules wędruje w głąb drugiego worktree.

  2. Wybierz narzędzie albo napisz skrypt. Trzy sensowne opcje: (a) zainstaluj Conductora, jeśli chcesz GUI na macOS; (b) zainstaluj Claude Squad, jeśli żyjesz w terminalu; (c) napisz ~30-linijkowy wrapper bashowy z góry. Nie wybieraj wszystkich trzech — wybierz jedno i używaj dwa tygodnie, zanim zaczniesz przemyśleć.

  3. Podłącz .env do kroku spawnowania. Każdy worktree startuje jako pusty checkout — git nie trackuje .env, .env.local, .dev.vars ani żadnego innego ignorowanego pliku, którego potrzebuje Twoja apka, żeby wystartować. Twój spawn script albo tool musi je skopiować z głównego checkout-u, bo inaczej agenty wywalą się na pierwszym npm run dev. (Conductor i Claude Squad mają na to hooki; bashowy wrapper wyżej robi to wprost.)

  4. Przeinstaluj zależności w nowym worktree. Każdy worktree potrzebuje własnego node_modules (albo .venv, albo target/), bo domyślnie nie są dzielone. Wbij to w krok spawnowania, żeby agenty lądowały w worktree, który już się buduje. Jeśli czas instalacji zaczyna boleć, popatrz na content-addressable store pnpm-a, Yarn PnP, albo patterny pip --target, które dzielą paczki pod spodem.

  5. Dodaj izolację portu/runtime’u per worktree. Wystarczy nawet jednolinijkowiec: wyprowadź port offset z nazwy katalogu worktree i wyeksportuj jako PORT/DATABASE_URL/itp. wewnątrz spawnowanego shellu. Jeśli używasz direnv, wrzuć .envrc do każdego worktree, który ustawia offset; jeśli Docker, ustaw COMPOSE_PROJECT_NAME na basename. Sprawdź, że dwa worktree mogą równocześnie odpalić swój dev server, zanim uznasz, że gotowe.

  6. Wystaw spawn worktree jako akcję na jeden klawisz. W Claude Code napisz skill w ~/.claude/skills/spawn-worktree-agent/SKILL.md, który dokumentuje jak utworzyć nowy worktree, skopiować env, zainstalować deps i odpalić agenta. W Cursorze użyj /worktree. W Conductorze albo Claude Squad zrobi to UI. Chodzi o to: spawnowanie nowego izolowanego agenta powinno zająć sekundy, nie minuty.

  7. Zdefiniuj scenariusz teardownu. Zdecyduj, co się dzieje, kiedy zadanie agenta jest skończone. Sensowne defaulty: PR się merguje, spawn tool detektuje, że branch został skasowany na remote i odpala git worktree remove, a cotygodniowy git worktree prune czyści maruderów. Jak pominiesz ten krok, w ciągu miesiąca będziesz miał cmentarzysko pół-skończonych worktree-ów.

  8. Stress-test z trzema równoległymi agentami. Odpal trzech na różnych zadaniach przeciwko temu samemu repo równocześnie. Potwierdź, że żaden nie zderza się z drugim na plikach, portach ani testowych bazach. Jeśli się zderzają, najpierw to napraw — nie skaluj do sześciu, zanim trzy nie zadziałają.

  • Osierocone worktree. git worktree add jest łatwy; git worktree remove i git worktree prune łatwo się zapomina. W miesiąc casual użytkowania będziesz miał osiem katalogów na dysku, których nikt nie wie po co — połowa na skasowanych branchach. Albo wbij teardown w to samo narzędzie, które spawnowało worktree, albo zaplanuj cotygodniowy audit git worktree prune && git worktree list.
  • Wspólne node_modules jako “oszczędność”. Symlinkowanie node_modules między worktree-ami “żeby zaoszczędzić dysk” to najpopularniejszy footgun, który ludzie sobie strzelają sami. Różne branche potrzebują różnych wersji depów; skrypty instalacyjne zakładają, że katalog jest ich; drift w lockfile-u powoduje fantomowe bugi. Niech każdy worktree ma własne node_modules, a jak dysk naprawdę jest na styk — polegaj na content store paczkomenadżera (pnpm, yarn berry).
  • Nieskopiowany .env. Pliki .env są w .gitignore, więc nie ma ich w świeżym worktree. Pierwszą akcją każdego agenta jest npm run dev, który się wywala, bo nie ma DATABASE_URL. Agent “naprawia” problem, wymyślając wartość, a Ty się nie orientujesz, dopóki coś nie wybuchnie. Zawsze kopiuj .env w kroku spawnowania.
  • Kolizje portów. Dwa worktree, oba odpalają npm run dev, oba chcą port 3000. Drugi wywala błąd, agent retry’uje, agent edytuje config, żeby użyć portu 3001 — i teraz ta zmiana wycieka do diffa. Rozwiąż to raz portem offsetowym i zapomnij.
  • Cursor / VSCode indexer zjadający CPU na każdym worktree. Każdy worktree jest dla edytora osobnym projektem; otwarcie ośmiu na raz przypina CPU. Albo zamykaj okna worktree, kiedy kończysz, albo użyj edytora “limit indexers” / “ignore worktree” w ustawieniach.
  • Traktowanie worktree jako wystarczających. Worktree są konieczne dla równoległej pracy agentów; nie są wystarczające. Testowe bazy, kolejki, sekrety, mockowane zewnętrzne serwisy — wszystko stateful, co żyje poza drzewem plików — nadal potrzebuje własnego scenariusza izolacji.
  • Worktree na main branchu. Worktree wskazany na main (albo Twój default branch) tworzy dwuznaczność, który katalog jest “tym prawdziwym”. Zawsze twórz worktree na świeżym branchu (git worktree add ../slug -b agent/slug), żeby było dokładnie jedno worktree na branch.
  • Potrafisz odpalić nowego agenta na nowym worktree w mniej niż 30 sekund, bez wpisywania ręcznie żadnej komendy git worktree.
  • Twój spawn workflow automatycznie kopiuje .env (i inne ignorowane-ale-potrzebne pliki) do nowego worktree.
  • Potrafisz wymienić narzędzie albo skrypt, który tworzy dla Ciebie worktree (Conductor, Claude Squad, Cursor /worktree albo własny wrapper bashowy).
  • Masz przynajmniej jeden przykład odpalenia dwóch równoległych agentów z dev serverami bez kolizji portów — port offsets, Docker project names albo narzędzie do izolacji runtime’u to ogarniają.
  • Masz scenariusz teardownu: kiedy zadanie się kończy, worktree znika w ciągu tygodnia, a nie wisi w nieskończoność.
  • git worktree list na realnym working repo pokazuje mniej niż ~10 wpisów i każdy potrafisz wyjaśnić.
  • Pytany potrafisz w jednym zdaniu wyjaśnić, dlaczego worktrees są konieczne, ale niewystarczające do izolacji równoległych agentów (runtime state żyje poza drzewem plików).