1. Параллельность не ускоряет — она усиливает
Когда разработчик впервые узнаёт о параллельных треках, их очень хочется превратить в универсальный ускоритель: «Сейчас запущу три сессии, четыре ветки и, если повезёт, к вечеру у меня будет готов продукт, а если не повезёт — очень интересная автобиография». Параллельность — усилитель. Хорошо нарезали задачу — экономите время. Плохо — быстрее производите хаос.
Если разобраться, что вообще такое параллельный трек: workstream — отдельный трек со своей целью, веткой, worktree, сессией и понятным финалом. Ключевое слово — независимый. Не можете в одном абзаце сказать, что должно получиться, какие файлы трогать и по какому сигналу работа закончена, — задачу рано выносить в поток.
Чтобы это не звучало абстрактно, посмотрим, как выглядит хороший кандидат для отдельного трека в нашем Commerce OS: «Вынести расчёт итоговой суммы checkout в отдельный сервис внутри src/checkout/*, не трогая payments и orders, закончить, когда целевые тесты зелёные и diff остаётся компактным». Плохой: «Разобраться, почему иногда ломается заказ, скидка, налоги и вообще что-то странное в оплате». Второе — клубок неизвестности: распутайте его в одной основной сессии, потом делите.
Параллельность не уменьшает неопределённость. Она делает её дороже.
Чтобы держать это в голове, удобно смотреть на жизненный цикл трека как на короткий инженерный конвейер:
flowchart TD
A[Задача] --> B[Контракт трека]
B --> C[Ветка + worktree]
C --> D[Изолированная сессия]
D --> E[Diff + проверки]
E --> F{Решение}
F -->|Принять| G[Merge]
F -->|Взять часть| H[Cherry-pick]
F -->|Отклонить| I[Cleanup]
G --> J[Запись в лог]
H --> J
I --> J
Если какого-то узла в этой цепочке у вас нет — например, нет явного решения в конце или нет проверок посередине, — это уже не управляемый трек, а надежда на лучшее. Надежда, конечно, иногда полезна, но Git её не индексирует.
2. Четыре уровня нельзя смешивать
Самая частая причина путаницы в параллельной работе — смешение уровней. Человек говорит «у меня есть ветка», а на деле имеет в виду сессию Claude. Или говорит «агент всё сделал», а потом выясняется, что в Git вообще пусто. Чтобы не попадать в такие ловушки, полезно чётко разделять четыре уровня: session, worktree, Git и human.
Удобно думать о них как об отдельных ролях в одной инженерной сцене. Сессия или агент исполняет задачу. worktree изолирует файлы. Git хранит историю и позволяет сравнивать состояния. Человек принимает решение и отвечает за итоговый компромисс. Как только вы начинаете ждать от одного уровня работу другого, начинается цирк с багами и красными глазами.
| Уровень | За что отвечает | Чего не делает |
|---|---|---|
| Сессия / агент | Выполняет конкретную работу, собирает контекст, меняет код или анализирует | Не хранит официальную историю проекта |
| worktree | Даёт отдельную папку и файловую изоляцию для трека | Не заменяет Git и не принимает решения |
| Git | Показывает diff, хранит коммиты, помогает с merge и rollback | Не знает, хорошее ли у вас архитектурное решение |
| Человек | Утверждает план, читает diff, решает merge / reject / split | Не должен вручную догадаться обо всём без артефактов и критериев |
Хорошая рабочая аналогия выглядит так: ветка — сюжетная линия, worktree — отдельный стол в мастерской, сессия — разговор у этого стола, а человек — редактор, который решает, войдёт ли сцена в финальную версию. Если вы посадили двух редакторов за один стол с одним и тем же текстом, не удивляйтесь, что потом никто не понимает, кто именно вычеркнул половину страницы.
На практике отсюда следует очень простая дисциплина. Если вы хотите, чтобы второй трек действительно был отдельным, создавайте для него отдельную папку через worktree и запускайте отдельную Claude-сессию именно в этой папке. Не надо держать одну сессию на main, вторую — «мысленно в соседнем мире», а третью — в режиме «я всё помню». Память разработчика — вещь благородная, но в пятницу после обеда она работает как кэш с произвольной политикой вытеснения.
3. Контракт трека до первого коммита
Прежде чем поднимать новый worktree, полезно зафиксировать очень маленький документ с ответом на вопрос: что вообще должен делать этот трек. Это не огромная спецификация и не дипломная работа. Это короткий контракт трека. В Workflow Kit такой шаблон удобно хранить рядом с handoff notes и review-шаблонами, чтобы команда каждый раз не изобретала одни и те же формулировки.
Вот минимальный вариант такого контракта:
# track-checkout-refactor.md
Цель: вынести расчёт итоговой суммы checkout в отдельный сервис
Worktree: ../commerce-os.checkout-flow
Входит в scope: src/checkout/*, tests/checkout/*
Не входит: src/payments/*, src/orders/*
Стоп-условие: Checkout-тесты зелёные, diff до 300 строк
Здесь нет ничего «умного», и в этом как раз его сила. Этот текст можно открыть за десять секунд и понять, что именно разрешено треку, а что запрещено. Если позже трек внезапно начинает менять src/payments/*, вы не спорите с агентом философски и не гадаете, «может, так тоже нормально». Вы просто видите, что трек вышел за границы.
Особенно важны две строки: не входит и стоп-условие. Первая защищает от доброго, но опасного «раз уж я тут был, я ещё чуть-чуть улучшил архитектуру». Вторая защищает от бесконечной жизни ветки. Трек без стоп-условия — это сериал, который давно надо было закрыть, но сценаристы всё ещё надеются на новый сезон.
Для начинающего разработчика здесь правило простое: если вы не можете написать строку «не входит в scope», не запускайте параллельный трек. Значит, вы пока не отделили задачу от окружающего тумана.
4. Worktree без магии
Слово worktree иногда звучит так, будто мы сейчас будем выращивать новый Git из почки старого Git. На деле всё гораздо прозаичнее и полезнее: worktree создаёт ещё одну рабочую директорию для того же репозитория, обычно на другой ветке. Это не полная копия проекта и не отдельный .git-мир. История и объекты у репозитория общие, а файлы на диске — отдельные. Поэтому вы можете одновременно держать main в одной папке, а рискованный рефакторинг — в другой.
Если ветки ещё нет, удобно создавать её прямо в момент добавления worktree:
git worktree add -b feature/checkout-refactor ../commerce-os.checkout-flow
cd ../commerce-os.checkout-flow
git status
# On branch feature/checkout-refactor
# nothing to commit, working tree clean
Если ветка уже существует, команда будет чуть короче: вы просто добавляете новую папку и привязываете её к уже готовой ветке. Для первого знакомства вариант с -b проще, потому что делает всё сразу и не заставляет держать в голове лишнюю развилку.
После этого полезно сразу посмотреть, какие worktree у вас уже существуют:
git worktree list
# /repo/commerce-os abcd123 [main]
# /repo/commerce-os.checkout-flow abcd123 [feature/checkout-refactor]
Этот вывод хорошо отрезвляет. Вы буквально видите, что у вас теперь две рабочие директории: одна живёт на main, вторая — на новой ветке. Проект один и тот же, но драки за одни и те же файлы в одной папке больше нет. Это особенно приятно, когда вы работаете не один на один с кодом, а вместе с агентом или отдельной Claude-сессией. Запускаете её из новой директории — и получаете по-настоящему изолированный трек, а не «ну я просто сейчас аккуратно не перепутаю».
Если у вас в Claude есть отдельная панель активных сессий или агентов, используйте её, чтобы наблюдать за запущенными треками. Название этого интерфейса может отличаться от версии к версии. Но даже если интерфейс очень красивый и уверенный в себе, источник истины всё равно остаётся прежним: папка worktree, Git-состояние и тесты.
5. Мониторинг по сигналам, не по тону
Когда трек уже запущен, появляется новый соблазн: следить за ним по сообщениям сессии. Агент пишет «завершил» — и вы выдыхаете. Агент пишет «почти готово» — и вы тоже выдыхаете, но уже чуть тревожнее. Проблема в том, что уверенный тон не является метрикой прогресса. Для мониторинга нужны проверяемые сигналы, и они, к счастью, довольно скучные. А скучное в инженерии часто означает надёжное.
Первый сигнал — состояние ветки: есть ли изменения, сколько их, закоммичены они или нет. Второй — размер diff. Он не доказывает качество, но быстро показывает, не превратился ли «маленький рефакторинг checkout» в роман-эпопею на полпроекта. Третий — целевые тесты. Четвёртый — короткая запись в логе трека: что уже проверили и к чему сейчас пришли.
Если вы сидите в основной папке проекта, а параллельный трек живёт в соседней, очень удобен ключ -C, который позволяет выполнять Git-команды сразу в нужной директории:
git -C ../commerce-os.checkout-flow status --short # пусто => рабочее дерево чистое
git -C ../commerce-os.checkout-flow diff --stat # смотрим текущий diff
( cd ../commerce-os.checkout-flow && ./gradlew test --tests "*Checkout*" )
# BUILD SUCCESSFUL
Этот набор выглядит почти слишком простым, чтобы быть полезным, но именно в этом его красота. Вы не спрашиваете «ну как там?», вы смотрите на состояние файлов и на результат проверки. Если diff неожиданно вырос с 40 строк до 700, это сигнал. Если тесты зелёные, это другой сигнал. Если status --short пустой, а сессия рассказывает, что «многое уже сделано», значит, либо всё уже закоммичено, либо пока ничего нет, и тогда надо проверить git log.
Чуть подробнее можно посмотреть набор коммитов, которых ещё нет в main:
git -C ../commerce-os.checkout-flow log --oneline main..HEAD
# 3fa12bc вынесен расчёт скидки в CheckoutTotalService
# a20b6de обновлены тесты checkout
Такой мониторинг особенно полезен, когда вы ведёте несколько треков сразу. Иначе через час начинается игра «а где был тот хороший diff, который вроде бы кто-то уже сделал». В какой-то момент разработка начинает напоминать сериал про детективов, а это плохой знак.
6. Решение по треку: accept, reject, split
Самый важный момент в параллельной работе — не запуск, а финальное решение. Трек должен заканчиваться не фразой «надо потом посмотреть», а явным исходом. В инженерной реальности у вас обычно есть четыре нормальных варианта: принять, взять часть, разделить или отклонить. Иногда ещё нужен revert, если ошибка обнаружилась уже после вливания, но это уже исправление позднего решения, а не базовый сценарий.
Удобно держать перед глазами короткую таблицу:
| Решение | Когда подходит | Что это значит |
|---|---|---|
| Принять | Scope соблюдён, diff понятный, проверки зелёные | Трек можно сливать целиком |
| Взять часть | Внутри трека есть полезный кусок и лишний кусок | Берём безопасные коммиты, остальное оставляем |
| Разделить | Трек решил две задачи сразу | Режем на два отдельных изменения |
| Отклонить | Трек ушёл в сторону или принёс больше риска, чем пользы | Сохраняем полезные заметки, код не вливаем |
Команда cherry-pick особенно полезна, когда трек принёс не «всё или ничего», а один хороший коммит внутри неудачной общей истории:
git switch main
git cherry-pick 3fa12bc # переносим только безопасный коммит
git revert 9ab44de # если уже слитый коммит дал регресс
Здесь важно не стесняться слова «отклонить». Разработчики, особенно в начале пути, часто жалеют уже проделанную работу: «ну агент же старался», «ну diff же красивый». А иногда дешевле выбросить трек, чем потом неделю разгребать последствия. Код не обижается. А продакшен иногда очень даже.
Очень полезно фиксировать решение в коротком логе, чтобы потом не вспоминать по памяти, почему именно не слили красивую ветку с ещё более красивым названием:
Decision: cherry-pick only tests from promo track; reject refactor in CartTotal.
Reason: checkout track owns src/checkout/*, promo track broke scope boundary.
Две строчки — а экономят массу времени будущему вам. А будущий вы обычно самый ворчливый reviewer в команде.
7. Cleanup как обязательная часть работы
В разработке есть особый вид самообмана — считать cleanup чем-то второстепенным. Мол, главное — полезные изменения, а убрать worktree и навести порядок можно потом. «Потом» — это либо «никогда», либо «через две недели, когда никто не помнит, что это за папка рядом с проектом». Так появляются кладбища worktree, старые ветки, ложное ощущение работы и странные CI-скрипты, которые смотрят не туда.
Хороший cleanup начинается не с удаления папки, а с вопроса: что из трека стоит сохранить как артефакт. Даже отклонённый трек даёт находку — кусок анализа, план, список рисков, хороший тест. Их выносят в лог трека, handoff note рядом с проектом или, если это уже reusable правило либо шаблон, — в отдельный markdown-файл в Workflow Kit. И только потом убирают папку.
Когда решение принято, удаление буднично:
git worktree remove ../commerce-os.checkout-flow
git branch -d feature/checkout-refactor # если ветка уже слита
git worktree prune # чистим служебные ссылки на удалённые worktree
Если внутри worktree остались незакоммиченные изменения, Git, скорее всего, не даст удалить его молча. И это очень правильное поведение. Это не «Git вредничает», это Git говорит: «сначала решите, мы сохраняем эту работу или сознательно выбрасываем». Если трек действительно надо выбросить, делайте это осознанно. Не через хаотичное удаление папки мышкой и последующее удивление, почему репозиторий теперь смотрит на вас с немым укором.
Особенно приятно, когда cleanup встроен в ритуал окончания трека. Приняли — убрали папку, почистили ссылки, обновили лог. Отклонили — сохранили полезные заметки, убрали папку, пометили решение. Тогда параллельная работа остаётся инструментом, а не начинает жить собственной жизнью рядом с проектом.
8. Артефакт parallel-session-log.md
Чтобы параллельные треки не оставались только в памяти разработчика и в глубинах терминала, полезно вести короткий лог. В Workflow Kit удобно хранить шаблон такого файла, а сам рабочий лог — рядом с текущим проектом и конкретным треком. Он не должен быть длинным. Его задача — за минуту ответить на вопросы: какой был трек, где он жил, что проверили, какое решение приняли и всё ли убрали после работы.
Например, так:
# parallel-session-log.md
## Трек
feature/checkout-refactor
## Сессия
checkout-refactor-2026-05-24
## Worktree
../commerce-os.checkout-flow
## Область изменений
src/checkout/*, tests/checkout/*
## Стоп-условие
Checkout-тесты зелёные, diff меньше 300 строк
## Проверено
- git diff --stat
- ./gradlew test --tests "*Checkout*"
## Решение
accept
## Сохранённые артефакты
- track-checkout-refactor.md
- review-notes.md
## Чистка
- worktree removed: yes
- branch removed: yes
Обратите внимание: здесь нет бюрократии ради бюрократии. Этот файл не дублирует Git и не пытается заменить PR. Он просто связывает вместе контекст трека, сигналы проверки и решение человека. Через несколько дней вы открываете его и сразу понимаете, что произошло. Через месяц другой разработчик открывает его — и тоже понимает. В этот момент параллельная работа перестаёт быть «магией, которую Вася как-то наколдовал в терминале», и становится нормальным командным процессом.
Если вы храните шаблоны таких логов в Workflow Kit, команда начинает лучше видеть повторяющиеся паттерны. Какие треки чаще принимаются целиком, какие чаще уходят в cherry-pick, какие почти всегда расползаются по scope. А это уже очень полезная инженерная обратная связь, даже без сложных метрик и красивых дашбордов.
Когда у вас есть отдельный worktree, короткий контракт трека, понятные сигналы мониторинга и внятный parallel-session-log.md, трек перестаёт быть туманным. И только после этого уже имеет смысл разбирать handoff внутри него: какие артефакты должны пережить смену этапа и что следующий участник получает на вход. Параллельная работа становится удивительно спокойной. Не драматичной, не «агентной», не хайповой — просто спокойной. А в инженерии это обычно и есть признак того, что вы всё делаете правильно.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ