Дополнительный источник: https://lzw.me/docs/opencodedocs/obra/superpowers/advanced/git-worktrees/index.html
Зачем это нужно
Второй шаг базового workflow (урок 17.5): дизайн согласован, и прежде чем писать план и код, работа изолируется — в отдельное рабочее дерево (worktree) и отдельную ветку. Без изоляции две беды: изменения фичи смешиваются с вашим текущим состоянием репозитория, и — важнее для агентов — сломанный бейзлайн тестов делает невозможным TDD (урок 17.10): каждый последующий шаг не отличает «сломали мы» от «уже было сломано».
Общим основаниям worktrees посвящен урок 10.3; здесь — перевод скилла using-git-worktrees: как Superpowers делает изоляцию обязательным шагом и какие ловушки в нем предусмотрены. Скилл короткий, но плотный: в нем больше «стоп-проверок», чем в любом другом, — потому что изоляция делается до того, как вы что-либо успели испортить.
Основная идея
Принцип скилла: «Detect existing isolation first. Then use native tools. Then fall back to git. Never fight the harness» — сначала обнаружь существующую изоляцию; потом используй нативные инструменты каркаса; только потом fallback на ручной git worktree; никогда не воюй с каркасом. В конце — обязательная проверка чистого бейзлайна тестов: рабочее дерево готово только тогда, когда тесты проходят на нетронутом дереве.
Шаг 0: обнаружить существующую изоляцию
До создания чего-либо скилл проверяет, не находимся ли мы уже в изолированном рабочем дереве:
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
BRANCH=$(git branch --show-current)
GIT_DIR != GIT_COMMON— уже linked worktree; создание еще одного запрещено, переход сразу к project setup. Отдельная ветка — обычное состояние; detached HEAD — «изолирован, управляется извне, ветка понадобится при завершении» (урок 17.12).- Guard на submodules:
GIT_DIR != GIT_COMMONверно и внутри git-субмодуля. Перед выводом «уже в worktree» проверка:
git rev-parse --show-superproject-working-tree 2>/dev/null
вернула путь — вы в субмодуле, обращаться как с обычным репо.
GIT_DIR == GIT_COMMON(или субмодуль) — обычный checkout. Если предпочтение worktree не задано заранее в инструкциях — вопрос согласия дословно:
Would you like me to set up an isolated worktree? It protects your current branch from changes.
Заданное заранее предпочтение выполняется без вопросов; отказ — работа на месте, шаг создания пропускается.
Шаг 1: создать изолированное рабочее пространство
Два механизма, в строгом порядке.
1a. Нативные инструменты (предпочтительны). Если у каркаса есть инструмент создания worktree — тул вроде EnterWorktree, WorktreeCreate, команда /worktree, флаг --worktree — используется он. Причина (важнейшее правило скилла): нативный инструмент владеет размещением каталога, созданием ветки и очисткой; ручной git worktree add мимо него создает «фантомное состояние», которое каркас не видит и которым не управляет.
1b. Fallback — ручной git worktree, только если нативного инструмента нет. Выбор каталога (по приоритету):
- заявленное в инструкциях предпочтение пользователя — без вопросов;
- существующий каталог проекта:
.worktrees(предпочтителен, скрытый) илиworktrees; если есть оба —.worktrees; - по умолчанию —
.worktrees/в корне проекта.
Проверка безопасности (обязательна для project-local каталогов): каталог обязан быть в .gitignore до создания worktree:
git check-ignore -q .worktrees 2>/dev/null || git check-ignore -q worktrees 2>/dev/null
Не игнорируется — добавить в .gitignore, закоммитить, только потом продолжать. Причина: неигнорируемый каталог worktree «коммитит» все дерево в репозиторий. Создание:
path="$LOCATION/$BRANCH_NAME"
git worktree add "$path" -b "$BRANCH_NAME"
cd "$path"
Если git worktree add падает по правам (песочница) — сообщить, что создание заблокировано, и работать в текущем каталоге: setup и бейзлайн-тесты на месте.
Шаг 2: project setup
Автодетект и запуск подходящей установки:
if [ -f package.json ]; then npm install; fi # Node.js
if [ -f Cargo.toml ]; then cargo build; fi # Rust
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
if [ -f pyproject.toml ]; then poetry install; fi # Python
if [ -f go.mod ]; then go mod download; fi # Go
Рабочее дерево свежее — зависимостей в нем нет, setup обязан пройти до бейзлайна.
Шаг 3: проверить чистый бейзлайн
Прогон тестов проектной командой (npm test / cargo test / pytest / go test ./...):
- падают — скилл обязан отчитаться о падениях и спросить, разбираться или продолжать. Это не формальность: бейзлайн, сломанный до старта, обесценивает TDD на всех последующих шагах — каждый красный тест двусмыслен.
- проходят — отчет готовности:
Worktree ready at <full-path>
Tests passing (<N> tests, 0 failures)
Ready to implement <feature-name>
Почему бейзлайн обязателен — формулировка скилла из таблицы рационализаций: «A dirty baseline makes every later failure ambiguous» — грязный бейзлайн делает двусмысленным каждое последующее падение. Связь с TDD — урок 17.10: RED-фаза предполагает, что до вашего теста все было зеленым.
Быстрая шпаргалка скилла
| Ситуация | Действие |
|---|---|
| Уже в linked worktree | ничего не создавать (шаг 0) |
| В субмодуле | как обычный репо (guard шага 0) |
| Есть нативный инструмент | использовать его (шаг 1a) |
| Нет нативного | fallback git worktree add (шаг 1b) |
Есть .worktrees/ / worktrees/ |
использовать, проверив игнор |
| Есть оба | .worktrees/ |
| Нет ни одного | инструкции, затем .worktrees/ по умолчанию |
| Каталог не игнорируется | добавить в .gitignore + коммит |
| Permission error при создании | fallback песочницы — работать на месте |
| Бейзлайн падает | отчитаться и спросить |
| Нет package.json/Cargo.toml | пропустить установку зависимостей |
Отмазки
Таблица рационализаций скилла (перевод выборки):
| Отмазка | Реальность |
|---|---|
| «Я очевидно не в worktree — проверять незачем» | Шаг 0. Изоляция от каркаса и субмодули оба обманывают глаз; команды детекции решают. |
«git worktree add быстрее, чем искать нативный тул» |
Нативный тул владеет размещением, веткой и очисткой. Обход — ошибка №1: фантомное состояние, которое каркас не видит. |
| «Каталог worktree наверняка уже игнорируется» | Запусти git check-ignore. Неигнорируемый каталог закоммитит все дерево в репо. |
| «Любое имя каталога сработает» | Явные инструкции > существующий project-local каталог > дефолт .worktrees/. |
| «Дерево свежее — бейзлайн подождет» | Грязный бейзлайн делает двусмысленным каждое падение. Прогони тесты сейчас; идти дальше через красное — решение партнера. |
Практика
На учебном репозитории пройдите цикл руками:
git rev-parse --git-dirи--git-common-dir— убедитесь, что вы в обычном checkout.- Создайте worktree:
git worktree add .worktrees/lesson-17 -b lesson-17. - До создания — проверьте
git check-ignore -q .worktrees; при необходимости добавьте в.gitignore. - Зайдите в worktree, выполните setup и прогоните тесты; зафиксируйте отчет в формате скилла.
Краткое резюме
Скилл using-git-worktrees делает изоляцию обязательным шагом перед исполнением: обнаружить существующую изоляцию → нативные инструменты каркаса → fallback на git worktree add в игнорируемый каталог → setup → чистый бейзлайн тестов.
- Guard-и: субмодуль неотличим от worktree на глаз — детекция командами; неигнорируемый каталог worktree — бомба под репозиторий.
- Нативный инструмент каркаса всегда приоритетнее ручного git: он владеет жизненным циклом worktree.
- Грязный бейзлайн обесценивает весь последующий TDD: сначала зеленое дерево, потом первый красный тест.
Вопросы для самопроверки
- Почему скилл запрещает создавать worktree, не проверив текущее состояние? Какие два состояния обманывают «на глаз»?
- Что не так с ручным
git worktree addпри наличии нативного инструмента каркаса? Какой термин использует скилл? - Зачем каталог worktree обязан быть в
.gitignoreи что произойдет, если это пропустить? - Почему проверка бейзлайна стоит до реализации, а не «по ходу»? Свяжите с RED-фазой TDD.
- Агент получил permission error при создании worktree — какие два действия предписаны?
Что дальше
Изоляция готова и бейзлайн зеленый — третий шаг: урок 17.8 разбирает writing-plans, скилл составления плана, исполняемого без истории обсуждения.