← Multi-agent orchestration: LangGraph, CrewAI, and agent teams
05 / 07 · 50 min

Parallel coding agents and git worktree

Several coding agents over one repository: why a shared directory is a wreck, a worktree and branch per stream, a queue with a concurrency limit, and safe merges.

Lesson content is currently available in Russian.

What you will learn

  • →Объяснять, какие именно гонки возникают у двух агентов в одном рабочем каталоге.
  • →Разворачивать и убирать worktree с веткой на каждый поток работы.
  • →Проектировать оркестратор кодинг-агентов: очередь, лимит параллельности, verify-gate и мёрж.

Почему общий каталог — авария

Кодинг-агент — не chat-бот: он материализует работу в файловой системе. Он читает файлы, правит их, запускает тесты и коммитит. Пустите двух таких агентов в один рабочий каталог — и вы получите все классические гонки конкурентного доступа, только с LLM в роли обоих гонщиков.

Сценарий первый: перекрёстное чтение недописанного. Агент А переписывает модуль авторизации; агент Б в этот момент читает тот же файл, видит половину рефакторинга и строит свою правку на состоянии, которого через минуту не будет. Итог — код, который не собирается, причём каждый агент по отдельности «прав». Сценарий второй: захват чужого WIP в коммит. Агент А делает git add . и коммитит — в коммит уезжают недоделанные файлы агента Б; история превращается в фарш, а откат одной задачи откатывает половину другой. Сценарий третий: гонка на индексе и ветках — два одновременных git add/git commit/git checkout в одном каталоге дерутся за index.lock, а переключение ветки одним агентом молча меняет файлы под ногами у второго.

Заметьте: ни одна из этих аварий не лечится «промптом получше». Это свойства общего изменяемого ресурса, и решение то же, что в многопоточном программировании, — изоляция. Каждому потоку работы нужен собственный каталог и собственная ветка, а точка слияния должна быть одна и управляемая. Ровно это и даёт git worktree.

Worktree и ветка на поток

git worktree создаёт дополнительный рабочий каталог, подключённый к тому же репозиторию: общая база объектов и рефов, но свой checkout, свой индекс и своя ветка. Это дешевле полного клона (объекты не дублируются) и главное — правильнее: ветки и коммиты видны из всех worktree сразу.

# каталог и ветка под каждый поток работы
git worktree add ../wt/auth-api -b feat/auth-api HEAD
git worktree add ../wt/auth-ui  -b feat/auth-ui  HEAD

git worktree list
# /repo          abc1234 [dev]
# /wt/auth-api   abc1234 [feat/auth-api]
# /wt/auth-ui    abc1234 [feat/auth-ui]

# после вливания или отказа — обязательная уборка
git worktree remove --force ../wt/auth-api
git worktree prune

Два правила, которые git защищает сам. Первое: одна ветка — один worktree; попытка сделать checkout ветки, уже занятой другим worktree, завершится ошибкой — это и есть страховка от двух агентов на одной ветке. Второе: worktree убирают командой git worktree remove, а не rm -rf; после ручного удаления каталога остаются висячие записи, которые чистит git worktree prune.

Конвенции, которые окупаются при десятках прогонов: единый корень для всех worktree (например, ~/worktrees/<repo>/ вне рабочих каталогов), имя каталога и ветки из слага задачи плюс таймстемп, и жёсткая привычка убирать worktree сразу после мёржа. Забытые worktree держат ветки занятыми и накапливаются в мусор, который потом страшно чистить.

Оркестратор поверх worktree

Изоляция каталогов решает гонки файловой системы, но не отвечает на вопросы планирования: сколько агентов пускать одновременно, кому какую задачу и что делать при отказе. Это работа оркестратора, и у него три обязательных механизма.

Первый — очередь с лимитом параллельности. Кодинг-агент — тяжёлый процесс: он гоняет typecheck, тесты и сборку, каждый экземпляр ест ядра и память. Практический потолок на рабочей машине — 2–4 одновременных агента; дальше прогоны начинают мешать друг другу через CPU, тесты флапают по таймаутам, и «параллельное» выполнение становится медленнее последовательного. Задачи сверх лимита ждут в очереди.

Второй — раскрой задач по непересекающимся областям файлов. Worktree изолирует процесс работы, но не смысл: если две задачи правят один модуль, конфликт никуда не делся — он просто отложен до мёржа. Оркестратор должен резать фронт работ так, чтобы области почти не пересекались (фронт/бэк, разные пакеты, разные фичи), а заведомо конфликтующие задачи ставить последовательно.

Третий — бюджет и таймаут на задачу. Каждому прогону — потолок в токенах, времени и итерациях; агент, упёршийся в потолок, останавливается и возвращает частичный результат с описанием затыка, а не крутится всю ночь. Отчёт агента обязан включать команду проверки и её вывод: «сделано» без зелёного прогона тестов — это не сделано, это гипотеза.

Сбор результата: verify-gate и мёрж

Финал параллельного прогона — свести N веток обратно в dev, не сломав его. Здесь дисциплина важнее ума, и порядок фиксированный.

Шаг первый: verify-gate внутри worktree. До всякого мёржа в каталоге задачи прогоняются typecheck, линт и тесты; ветка, не прошедшая ворота, в очередь мёржа не попадает — она возвращается агенту на доработку или человеку на разбор. Ворота должны быть механическими: скрипт с exit-кодом, а не «агент сказал, что всё хорошо».

Шаг второй: коммит только своих файлов, поимённо. git add . в агентном конвейере запрещён как класс: даже в изолированном worktree агент мог насорить временными файлами, а привычка тащить всё подряд рано или поздно захватит чужое. Коммит-сообщение — по Conventional Commits, со слагом задачи.

Шаг третий: последовательный мёрж. Ветки вливаются в dev по одной; после каждого мёржа dev-прогон тестов повторяется, потому что две ветки, зелёные порознь, вместе могут быть красными — классика семантических конфликтов: одна переименовала функцию, вторая добавила её вызов по старому имени. Если ветка устарела относительно dev, её сначала перебазируют и прогоняют ворота заново.

Шаг четвёртый: ревью-агент на диффе. Отдельный агент (или человек) читает git diff dev...feat/x перед мёржем — свежий контекст без истории прогона находит то, что автор-агент уже «не видит». И финальный аккорд: worktree удалён, ветка удалена, git worktree list чист. Уборка — часть definition of done.

Practice

Два агента параллельно в worktree

Возьмите учебный репозиторий с тестами и запустите двух кодинг-агентов (Claude Code, Codex CLI или аналог) на двух непересекающихся задачах — каждого в своём worktree со своей веткой. Прогоните verify-gate в обоих каталогах, влейте ветки в dev последовательно с повторным прогоном тестов после каждого мёржа, уберите worktree.

Deliverable

История команд: создание worktree, вывод git worktree list, зелёные прогоны тестов в обеих ветках и в dev после каждого мёржа, чистый git worktree list в конце.

Checkpoint

Коллега предлагает запустить трёх кодинг-агентов в общем каталоге, «потому что worktree — лишняя возня». Разубедите его конкретными сценариями аварий.

  • ✓ Названы минимум две конкретные гонки: чтение недописанного, захват чужого WIP через git add ., драка за индекс/ветки.
  • ✓ Объяснено, что worktree дёшев (общие объекты) и что git сам запрещает одну ветку в двух worktree.
  • ✓ Упомянут verify-gate и последовательный мёрж с повторным прогоном тестов.

Check yourself

Что делит и что НЕ делит дополнительный worktree с основным каталогом?

01Что делит и что НЕ делит дополнительный worktree с основным каталогом?

Почему git add . запрещён в агентном конвейере?

02Почему git add . запрещён в агентном конвейере?

Зачем повторять прогон тестов в dev после КАЖДОГО мёржа, если обе ветки были зелёными?

03Зачем повторять прогон тестов в dev после КАЖДОГО мёржа, если обе ветки были зелёными?

Почему лимит параллельности кодинг-агентов на машине — обычно 2-4, а не 20?

04Почему лимит параллельности кодинг-агентов на машине — обычно 2-4, а не 20?

Sources

Parallel coding agents and git worktree · Multi-agent orchestration: LangGraph, CrewAI, and agent teams · VORCL