Перейти до основного змісту
Версія: Next

pnpm + робочі дерева Git для розробки з використанням декількох агентів

Коли декілька агентів штучного інтелекту мають одночасно працювати з одним і тим самим монорепозиторієм, кожному з них потрібна ізольована робоча копія з повністю функціональною текою node_modules. Робочі дерева Git у поєднанні з глобальним віртуальним сховищем від pnpm роблять це практичним: кожне робоче дерево отримує свою власну копію та власні node_modules, але залежності спільно використовуються всіма ними через єдине сховище на диску з адресацією за вмістом.

Що таке робоче дерево git?

Зазвичай репозиторій Git має одну робочу теку, яка одночасно пов’язана з однією гілкою. Якщо ви хочете переглянути іншу гілку, вам потрібно зберегти (додати зміни в stash) або зафіксувати зміни та переключитися неї. Git worktree дозволяє одночасно завантажувати кілька гілок, кожна з яких зберігається у власній теці. Усі робочі дерева мають однакову історію та об'єкти репозиторію — це просто різні представлення одного й того ж репозиторію.

git worktree add ../feature-branch feat/my-feature

У результаті створюється нова тека ../feature-branch із вибраною гілкою feat/my-feature, тоді як ваша початкова робоча тека залишається на поточній гілці. Ви можете працювати в обох теках незалежно.

Поширеною схемою є використання голого репозиторію (такого, що не має власної робочої теки) як центру та створення всіх робочих тек як робочих дерев:

git clone --bare https://github.com/your-org/your-repo.git your-repo
cd your-repo
git worktree add ./main main
git worktree add ./feature feat/something

Чому саме робочі дерева?

Ще до появи агентів штучного інтелекту, робочі дерева були корисними для підтримки кількох основних версій проєкту. На своїй робочій машині я використовую репозиторій pnpm, що містить щонайменше дві робочі гілки: одну в гілці main для pnpm v11 та іншу в гілці v10 для бекпортів та випусків з виправленнями. Таким чином я можу виправити помилку у версії 10, не відкладаючи роботу над версією 11 в stash, яка ще триває — обидві версії завжди доступні для роботи. Раніше мені зазвичай було достатньо 2 або 3 робочих дерев у репозиторії pnpm. Однак, оскільки я почав широко використовувати агентів зі штучним інтелектом, мені потрібно набагато більше робочих дерев, щоб мої агенти могли працювати над багатьма завданнями паралельно.

Чому це має ще більше значення у випадку з агентами ШІ

Завдяки агентам з кодування на основі штучного інтелекту робочі дерева перетворюються з зручного інструменту на незамінний. Кожному агенту потрібна власна робоча тека для редагування файлів, запуску збірок та виконання тестів, щоб не заважати роботі інших агентів. Без використання робочих дерев це означає багаторазове клонування репозиторію, що призводить до дублювання історії Git для кожної копії.

Worktrees вирішують питання, пов’язані з Git: кожен агент отримує власний ізольований доступ, при цьому спільно використовуючи базові об’єкти Git. Але кожне робоче дерево все ще потребує власних node_modules, які можуть бути розміром сотні мегабайт. Ось тут і приходить на допомогу глобальне віртуальне сховище від pnpm: якщо його ввімкнути, node_modules кожного робочого дерева містить лише символічні посилання в одне сховище на диску, до якого можна адресувати вміст. Це означає, що додавання нового агента відбувається швидко та майже не потребує додаткового місця на диску.

Налаштування

1. Створіть голий репозиторій

git clone --bare https://github.com/your-org/your-monorepo.git your-monorepo
cd your-monorepo

2. Створіть робочі дерева для кожної гілки

# Головне дерево розробки
git worktree add ./main main

# Гілка функцій для агента A
git worktree add ./feature-auth feat/auth

# Гілка виправлення помилок для агента B
git worktree add ./fix-api fix/api-error

Кожне робоче дерево — це повна копія репозиторію зі своїми файлами, але всі вони використовують одне й те саме сховище об’єктів .git.

3. Активуйте глобальне віртуальне сховище

Додайте enableGlobalVirtualStore: true до pnpm-workspace.yaml у вашому репозиторії:

packages:
- 'packages/*'

enableGlobalVirtualStore: true

4. Встановіть залежності для кожного робочого дерева

cd main && pnpm install
cd ../feature-auth && pnpm install
cd ../fix-api && pnpm install

Перша команда pnpm install завантажує пакунки до глобального сховища. Подальші встановлення в інші робочі дерева відбуваються майже миттєво, оскільки вони створюють лише символічні посилання на те саме сховище.

Як це працює

Без глобального віртуального сховища кожне робоче дерево мало б власне віртуальне сховище .pnpm всередині node_modules з жорсткими посиланнями або копіями кожного пакунка. З параметром enableGlobalVirtualStore: true, pnpm зберігає весь вміст пакунка в одній спільній теці (глобальному сховищі, яке можна знайти, виконавши команду pnpm store path), а node_modules кожного робочого дерева містить символічні посилання, що вказують туди:

your-monorepo/                      (bare git repo)
├── main/ (worktree: main branch)
│ ├── packages/
│ └── node_modules/
│ ├── lodash → <global-store>/links/@/lodash/...
│ └── express → <global-store>/links/@/express/...
├── feature-auth/ (worktree: feat/auth branch)
│ └── node_modules/
│ ├── lodash → <global-store>/links/@/lodash/... ← same target
│ └── express → <global-store>/links/@/express/...
└── fix-api/ (worktree: fix/api-error branch)
└── node_modules/
├── lodash → <global-store>/links/@/lodash/... ← same target
└── express → <global-store>/links/@/express/...

Це означає:

  • Майже нульові накладні витрати на кожне робоче дерево — локальний node_modules містить лише символічні посилання на спільне глобальне віртуальне сховище. На відміну від стандартної поведінки pnpm, яка створює жорсткі посилання на файли зі сховища з адресацією за вмістом у локальну теку node_modules/.pnpm, глобальне віртуальне сховище означає, що файли взагалі не копіюються і не повʼязуються жорсткими посиланнями у робочому дереві.
  • Миттєве встановлення нових робочих дерев — пакунки вже є в глобальному сховищі.
  • Жодних конфліктів — кожне робоче дерево має своє дерево `node_modules', тому агенти можуть встановлювати різні версії залежностей з різних гілок без перешкод одни одному.

Як приклад монорепо pnpm

У репозиторії pnpm використовується саме така конфігурація з «голим» репозиторієм Git та параметром enableGlobalVirtualStore: true. Він містить допоміжні скрипти для спрощення керування робочим деревом:

pnpm worktree:new <branch-name|pr-number> — створює нове робоче дерево та налаштовує його:

# Створення рабочого дерева для гілки (якщо воно не існує, створюється на основі гілки main)
pnpm worktree:new feat/my-feature

# Створення робочого дерева для PR на GitHub (автоматично завантажує посилання на PR)
pnpm worktree:new 10834

Цей скрипт обробляє кілька речей, окрім простого виконання git worktree add:

  • Номери PR отримуються через git fetch origin pull/<number>/head, тому вони також працюють для форків.
  • Назви гілок зі скісними рисками (наприклад, feat/my-feature) перетворюються на дефіси для назви теки (наприклад, feat-my-feature).
  • Тека .claude підключена символічним посиланням із загальної теки git голого репозиторію до нового робочого дерева, тому всі робочі дерева використовують однакові налаштування Claude Code та затверджені команди.

Також є допоміжна програма оболонки shell/wt.sh, яка обгорнує скрипт і виконає команду cd у нове робоче дерево:

# Вкажіть це у файлі конфігурації оболонки, а потім:
wt feat/my-feature
wt 10834

Поради

  • Створення робочих дерев для агентів: Під час запуску агента штучного інтелекту створіть для нього окреме робоче дерево. Агент отримує повну ізоляцію для редагування файлів, запуску тестів та встановлення пакунків, не впливаючи на інших агентів.
  • Очищення: Видаліть робоче дерево, коли воно більше не потрібне, за допомогою git worktree remove ./feature-auth. Залишки робочих дерев не є витратними, але можуть накопичуватися.