Использование Git Worktrees с ИИ-агентами для написания кода
Используйте git worktrees с ИИ-агентами, чтобы изолировать ветки, избежать конфликтов файлов и безопасно управлять портами, БД и слияниями.
Надёжный способ запускать несколько ИИ-агентов на одном репозитории — придерживаться схемы «одна задача, одна ветка, один worktree, один агент»: каждый агент получает собственный каталог, созданный через git worktree add, работает в собственной ветке и никогда не трогает файлы, которые редактирует другой агент.
Большинство разработчиков приходят к этому паттерну на собственном горьком опыте. Два агента в одном рабочем каталоге незаметно перезаписывают друг другу недоделанные правки, или один из них намертво зависает при попытке переключиться на ветку, уже извлечённую в другом месте. Эта статья — именно про рабочий процесс с агентами: что паттерн изолирует, что он сознательно не изолирует и что делать, когда три агента заканчивают работу одновременно.
Ключевые выводы
- Запускайте по одному агенту на worktree:
git worktree add ../task-a -b agent/task-a mainдаёт каждому агенту изолированный каталог и ветку. - Worktrees изолируют файлы, но не среду выполнения: порты, базы данных и Docker-тома принадлежат машине, поэтому назначьте каждому worktree отдельный порт и отдельную базу данных.
- Новый worktree содержит только отслеживаемые файлы; выполните
npm ciи скопируйте.envперед запуском агента. - Ветка может быть извлечена только в одном worktree, поэтому укажите агентам никогда не выполнять
git checkoutилиgit switch. - Сливайте готовые ветки по одной, каждый раз выполняя rebase на обновлённый
mainперед слиянием.
Паттерн Git Worktree для ИИ-агентов
Паттерн «один агент — один worktree» требует двух команд на задачу. Создайте worktree с новой веткой на основе main, а затем запустите внутри него агента:
git worktree add ../task-a -b agent/task-a main
git worktree add ../task-b -b agent/task-b main
Направьте одного агента в ../task-a, а другого — в ../task-b. У каждого будет свой рабочий каталог, свой индекс и свой HEAD, при этом все worktrees используют общую базу объектов и общие ссылки (refs), поэтому коммиты, сделанные в одном, сразу видны из остальных. Привязывайте worktree к задаче, а не к агенту: создавайте его в начале работы и удаляйте, когда ветка слита. Anthropic описывает ту же последовательность действий вручную в руководстве по worktrees для Claude Code, а Cursor запускает агентов в изолированных worktrees из окна Agents Window; Codex работает точно так же, если указать ему каталог.
Почему один общий каталог не работает?
Два агента в одном каталоге дают сбой молча: ни git, ни сами агенты не выдают ошибку, когда один перезаписывает незакоммиченные правки другого, поэтому ущерб обнаруживается только на этапе ревью. Механизм обнаружения конфликтов в git сравнивает коммиты; параллельные записи в одно и то же рабочее дерево до него просто не доходят.
Второй тип сбоя заметнее, но хуже. Параллельные операции git в общем каталоге сталкиваются на .git/index.lock, и если агент падает, удерживая блокировку, оставшийся файл блокирует git-команды всех остальных агентов, пока кто-нибудь не удалит его вручную. Одни агенты повторяют попытку; другие бросают коммитить и продолжают генерировать код поверх неограниченно растущего незакоммиченного состояния. Отдельные worktrees устраняют обе проблемы, поскольку каждый worktree индексирует изменения в собственный индекс, а не в общий.
Чего не содержит новый worktree
Новый worktree содержит только отслеживаемые файлы, поэтому node_modules, .env, кэши сборки и всё остальное, что перечислено в gitignore, отсутствует, пока вы это не создадите. Агент, запущенный в «голом» worktree, провалит первый же прогон тестов или, что хуже, «услужливо» перепишет конфигурацию, чтобы это компенсировать. Подготавливайте каждый worktree до запуска агента:
cd ../task-a
npm ci
cp ../main-repo/.env .env
npm ci — правильный выбор для установки здесь: команда создана для чистых окружений и устанавливает ровно то, что указано в lock-файле. Если ваш агент — Claude Code, файл .worktreeinclude может переносить gitignored-файлы вроде .env в worktrees, которые Claude Code создаёт сам, но он не действует на worktrees, созданные вручную через git worktree add, — поэтому ручное копирование работает с любым инструментом.
Что worktrees не изолируют
Worktrees изолируют файлы, но не среду выполнения: порты, базы данных, Docker-тома и общие кэши принадлежат машине, поэтому два dev-сервера, запущенные из двух worktrees, всё равно будут конкурировать за порт 3000. Граница каталога ничего не значит для всего, что адресуется по имени хоста или порту.
| Изолировано в каждом worktree | Общее для всей машины |
|---|---|
| Рабочие файлы, незакоммиченные правки | TCP-порты |
| Индекс (staging area) | Базы данных |
Извлечённая ветка / HEAD | Docker-тома и демон |
| Результаты сборки внутри каталога | Глобальные кэши пакетов |
Выделите каждому worktree собственный порт и собственную базу данных до запуска агента, который выполняет миграции, потому что изменение схемы, сделанное из одного worktree, попадёт в любую базу, которую используют остальные. Задайте оба параметра в скопированном .env:
# ../task-a/.env
PORT=3001
DATABASE_URL=postgres://localhost:5432/app_agent_task_a
Именование базы по названию ветки упрощает поиск и последующее удаление устаревших. Контейнеры тоже могут изолировать уровень выполнения, но связанные с этим компромиссы тянут на отдельную статью.
Как сообщить агенту, что он находится в worktree?
Ветка может быть извлечена только в одном worktree одновременно, поэтому агент, пытающийся синхронизироваться командой git checkout main, получает ошибку и часто зависает. Руководство по git checkout описывает это поведение и указывает --ignore-other-worktrees как способ его обойти. Не позволяйте агенту выяснять это во время работы; пропишите правило в файле инструкций, который агент читает (AGENTS.md, CLAUDE.md или аналогичный):
You are working inside a git worktree.
Stay on the current branch. Never run `git checkout` or `git switch`.
To sync with main, run `git fetch origin` and `git rebase origin/main`.
Когда агенту нужно только прочитать или собрать конкретный коммит, ветки не нужны вовсе: git worktree add --detach создаёт worktree с отсоединённым HEAD, что полностью обходит правило исключительности.
git worktree add --detach ../review-b1a2c3 b1a2c3
Как сливать то, что вернулось?
Worktrees не устраняют конфликты слияния; они переводят их из разряда молчаливых перезаписей во время выполнения в разряд явных конфликтов на этапе слияния, где с ними справляется обычный инструментарий git. Когда несколько агентов заканчивают одновременно, интегрируйте результаты последовательно: слейте одну ветку, выполните rebase следующей на обновлённый main, слейте её и повторите.
cd ../main-repo
git merge agent/task-a
cd ../task-b
git rebase main
cd ../main-repo
git merge agent/task-b
Каждый rebase выявляет конфликты со всем, что уже слито, по одной ветке за раз, вместо того чтобы накапливать трёхсторонние сюрпризы. Правило упорядочивания находится выше по потоку, чем само слияние: задачи, которые затрагивают одни и те же файлы или где одна потребляет результат другой, нужно выполнять последовательно, а не параллельно. Никакая организация worktrees не исправит декомпозицию задач, которая изначально не была независимой.
Сколько агентов и когда убирать за собой
Практический потолок задаёт не git и не диск, а ваша пропускная способность на ревью, поскольку каждый параллельный агент производит ветку, которую нужно прочитать, протестировать и слить. Команды, публикующие материалы об этом процессе, например инженерная команда incident.io, описывают одновременный запуск четырёх-пяти агентов, но большинству разработчиков хватает и меньшего числа. Когда ветка слита, выполните git worktree remove ../task-a; поскольку при подготовке появились неотслеживаемые файлы, скорее всего понадобится --force — его git worktree remove требует для «грязных» worktrees. Если каталог был удалён через rm -rf, команда git worktree prune очистит устаревшие метаданные, которые git всё ещё хранит.
Начните с двух агентов
Схема «одна задача, одна ветка, один worktree, один агент» превращает параллельных агентов из источника незаметных повреждений в набор веток, пригодных для ревью. Начните с двух: создайте worktrees, подготовьте каждый с помощью npm ci и отдельного .env для задачи, добавьте инструкцию «оставайся в своей ветке» и отработайте последовательность rebase-затем-merge, прежде чем масштабироваться сверх того, что вы реально способны отревьюить.
Часто задаваемые вопросы
Что использовать для параллельного запуска ИИ-агентов: git worktrees или отдельные клоны?
Worktrees обычно предпочтительнее, потому что они используют общую базу объектов: коммит, сделанный в одном worktree, сразу виден из остальных без push и fetch, а история хранится на диске в единственном экземпляре. Отдельные клоны дублируют всю историю и требуют push и fetch для обмена коммитами. Клоны выигрывают только тогда, когда нужна полная изоляция — например, в репозиториях с сабмодулями.
Работают ли git worktrees с репозиториями, использующими сабмодули?
Лишь частично. Собственное руководство git по worktree относит поддержку сабмодулей к разделу BUGS, называет множественное извлечение экспериментальным и не рекомендует извлекать суперпроект более чем в одном месте одновременно. Кроме того, worktree с сабмодулями нельзя переместить командой git worktree move. Для параллельной работы агентов над репозиторием с сабмодулями отдельные полные клоны — более безопасный механизм изоляции, даже несмотря на дублирование истории и необходимость push для обмена коммитами между рабочими копиями.
Используют ли все git worktrees одну и ту же конфигурацию git?
Да. Каждый worktree читает одну и ту же конфигурацию репозитория, если вы явно не откажетесь от этого. Чтобы задать отдельному worktree собственные настройки, выполните git config extensions.worktreeConfig true, а затем записывайте значения через git config --worktree — они попадут в файл config.worktree этого worktree. Компромисс: старые версии Git не смогут открыть репозиторий после включения этого расширения.
Удаляет ли удаление worktree ветку агента?
Нет. Ветки — это ссылки (refs), общие для всего репозитория, поэтому git worktree remove удаляет рабочий каталог и его метаданные, но оставляет ветку и все её коммиты нетронутыми. Теряются только незакоммиченные изменения в этом каталоге — именно поэтому remove отказывается удалять «грязные» worktrees без флага --force. Ветку удаляйте отдельно командой git branch -d после слияния.