В ветке каталога осталась незавершённая правка, а исправление доставки нужно проверить отдельно. Создадим вторую рабочую папку через git worktree: текущие файлы останутся на месте, а новая задача получит собственную ветку и окружение.

Две ветки — две рабочие папкиДве ветки — две рабочие папкиОбщая база GitПапка worktree-lab/Ветка feature/catalogНезавершённые правки остаютсяПапка worktree-delivery/Ветка fix/deliveryОтдельный набор рабочих файловОкружение и зависимости второй папки готовим отдельно.
У worktree общая база Git, а рабочие файлы находятся в разных папках. Это позволяет заняться второй веткой, сохранив незавершённую работу в первой.

Проверьте, какую работу нужно сохранить

Нужны Git, терминал и базовые команды status, add, commit. Пример использует локальный учебный репозиторий без удалённого сервера. Команды для создания файлов рассчитаны на macOS, Linux или Git Bash в Windows.

Worktree — рабочая папка, связанная с общим репозиторием Git. У каждой такой папки свои файлы, индекс и текущая ветка. Коммиты и ссылки веток остаются общими. Поэтому для второй задачи не понадобится заново клонировать весь репозиторий.

В своём проекте сначала выполните:

git status --short --branch
git worktree list

Первая команда показывает текущую ветку и изменения. Вторая — уже существующие рабочие папки. Это полезный снимок до нового действия: вы увидите, какая ветка занята и куда случайно можно было бы положить ещё один проект.

Для обучения создадим отдельную папку. Не выполняйте команды инициализации внутри существующего рабочего репозитория. Выберите место для опытов и запустите:

mkdir worktree-lab
cd worktree-lab
git init -b main
git config user.name 'Учебный разработчик'
git config user.email 'learner@example.invalid'
git config commit.gpgsign false
printf 'Доставка: 350 рублей\n' > delivery.txt
printf 'Каталог книг\n' > catalog.txt
printf '*.local\n' > .gitignore
git add delivery.txt catalog.txt .gitignore
git commit -m 'Добавляет каталог и доставку'

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

Перейдите к незавершённой задаче:

git switch -c feature/catalog
printf 'Раздел: атласы\n' >> catalog.txt
git status --short --branch

Ожидается ветка feature/catalog и строка изменения catalog.txt. Строка пока не закоммичена. Именно это состояние мы хотим сохранить, пока работаем над доставкой.

Создайте папку для исправления от main

Находясь в worktree-lab, выполните:

git worktree add -b fix/delivery ../worktree-delivery main
git worktree list

Команда создаст папку worktree-delivery рядом с исходной, новую ветку fix/delivery и возьмёт за её начальное состояние main. Теперь в списке две папки: worktree-lab с feature/catalog и worktree-delivery с fix/delivery.

Начальная ветка указана намеренно. Если опустить main, новая ветка начнётся от текущего коммита, а в рабочем проекте это может оказаться промежуточная версия большой функции. Исправлению доставки нужна выбранная база, и её лучше назвать прямо.

Перейдите во вторую папку и сравните состояние:

cd ../worktree-delivery
git status --short --branch
cat catalog.txt

Статус должен быть чистым, имя ветки — fix/delivery. В catalog.txt будет только «Каталог книг»: незакоммиченная строка из первой папки сюда не переносится.

Теперь проверьте первую папку, не переключая её ветку:

git -C ../worktree-lab status --short --branch
git -C ../worktree-lab diff -- catalog.txt

Правка «Раздел: атласы» по-прежнему на месте. Параметр -C выполняет команду Git в указанной папке. Так можно проверить соседнее рабочее дерево из того же терминала и не потерять текущую папку.

Мы не откладывали изменения через git stash и не создавали промежуточный коммит только ради переключения задачи. Первая задача осталась в исходном состоянии. Второе дерево началось с выбранного коммита и получает собственные изменения.

Выполните исправление во второй ветке

Убедитесь, что терминал всё ещё в worktree-delivery, и измените учебную стоимость:

printf 'Доставка: 250 рублей\n' > delivery.txt
git diff -- delivery.txt

В разнице ожидается замена 350 на 250. Перед коммитом проверьте, какие файлы попадут в него:

git status --short
git add delivery.txt
git diff --cached -- delivery.txt
git commit -m 'Исправляет стоимость доставки'

Ветка fix/delivery получила коммит. Включён только delivery.txt; каталога в изменении нет. Это удобно для отдельного ревью или проверки исправления.

В учебном примере достаточно просмотра текста. В приложении запускайте проверку, которая подтверждает поведение исправления: тест расчёта, сборку или выбранный сценарий интерфейса. Сам факт создания второй папки качество исправления не проверяет.

Посмотрите на обе папки ещё раз:

git status --short --branch
git -C ../worktree-lab status --short --branch
git -C ../worktree-lab diff -- catalog.txt

Во второй папке чисто. В первой остаётся незавершённая правка каталога. Это основной результат опыта.

Подготовьте окружение каждой папки

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

Для проекта на npm с сохранённым package-lock.json установите зависимости из второй папки:

npm ci

Эта команда относится к реальному проекту с npm, в нашем текстовом стенде package.json нет. Не запускайте её ради самого worktree. Порядок подготовки зависит от проекта: прочитайте его инструкцию, затем установите зависимости тем менеджером, который уже выбран командой.

npm ci заменяет содержимое node_modules текущего проекта. Проверьте папку терминала перед запуском. Общая символьная ссылка на node_modules другой ветки может привести к тому, что установка одной задачи сломает окружение второй. Для начала держите зависимости отдельно; оптимизацию места оставьте до появления измеримой необходимости.

Локальный .env.local тоже потребуется подготовить осознанно. Подготовьте учебную или тестовую конфигурацию по принятой в проекте инструкции. Не копируйте рабочие секреты во все папки по привычке и не добавляйте их в коммит.

Для проверки сохранности локальных настроек создайте в worktree-delivery учебный .env.local:

printf 'VITE_DELIVERY_LABEL=Учебная доставка\n' > .env.local

Правило *.local в созданном нами .gitignore исключает файл из обычного статуса Git. При завершении работы мы отдельно сохраним эту настройку вне удаляемого дерева.

Если одновременно запускаются два сервера разработки Vite, назначьте им разные порты. Например, из первой и второй папок соответственно:

npm run dev -- --port 5173 --strictPort
npm run dev -- --port 5174 --strictPort

Флаг --strictPort помогает заметить занятый порт, вместо того чтобы открыть страницу соседнего процесса и проверять старый код. У другого инструмента параметры могут отличаться: посмотрите его команду запуска.

Папки разные, но процессы используют ту же машину. Они могут обращаться к одной базе данных, менять общий кеш, читать одну домашнюю папку или обращаться к внешнему сервису с одинаковыми полномочиями. Worktree не создаёт защитную песочницу для процессов. Для изоляции данных и опасных действий нужен отдельный предусмотренный проектом механизм.

Разберитесь с общей историей

До коммита исправления вторая ветка и main указывали на одну исходную точку. Теперь fix/delivery указывает на исправление. Файлы первой папки всё ещё показывают feature/catalog с её незавершённой строкой.

Проверьте ссылки:

git log --oneline --all --decorate --graph -5

Коммит исправления виден из обеих папок: они используют один репозиторий. Обмена с удалённым сервером здесь нет.

Предскажите результат перед опытом: можно ли открыть feature/catalog во второй папке, когда первая уже использует эту ветку? Попробуйте из worktree-delivery:

git switch feature/catalog

Git должен отказать, потому что ветка уже открыта в другом рабочем дереве. Это защита от рассогласования двух наборов файлов, которые пытались бы совместно двигать одну текущую ветку. После отказа git status --short --branch должен всё ещё показывать fix/delivery.

Для второй задачи выбирайте другую ветку. Если вам нужна только проверка определённого коммита без работы в именованной ветке, существует отдельный сценарий с detached HEAD; в этом опыте он не требуется. Не обходите защиту принудительными флагами ради обычной параллельной работы.

Общая история означает и общие действия со ссылками. Если удалить ветку, создать тег или выполнить fetch, другие деревья тоже увидят результат. Незакоммиченные файлы и индекс у каждой папки свои. Держите эту границу в голове, когда смотрите status и log: команды показывают разные стороны состояния.

Завершите задачу и освободите папку

Перед удалением worktree убедитесь, что работа сохранена, тесты пройдены, а нужный коммит доступен по ветке. В учебном сценарии перенесём исправление в main через обычное слияние.

Вернитесь в первую папку. Сначала завершим правку каталога, чтобы оставить чистое дерево:

cd ../worktree-lab
git diff -- catalog.txt
git add catalog.txt
git commit -m 'Добавляет раздел атласов'

Теперь переключитесь на main и примите исправление доставки:

git switch main
git merge --ff-only fix/delivery
cat delivery.txt

В нашем стенде main не расходилась с fix/delivery, поэтому при слиянии Git сдвинет указатель main к коммиту исправления. Ожидаемый текст — «Доставка: 250 рублей». Ветка каталога с отдельным коммитом сохранена и пока не объединена с main.

В командном репозитории вместо локального слияния используйте принятый процесс ревью. Worktree не меняет правила попадания кода в основную ветку.

Остановите процессы второй папки, закройте там терминалы и проверьте как обычные изменения, так и игнорируемые файлы:

git -C ../worktree-delivery status --short --branch
git -C ../worktree-delivery status --short --ignored

Второй вывод должен содержать !! .env.local: файл исключён из обычного статуса. Сохраните нужные локальные настройки и данные вне удаляемой папки. В нашем учебном примере вы находитесь в worktree-lab; создайте папку для копии и сравните файлы:

mkdir local-settings
cp ../worktree-delivery/.env.local local-settings/delivery.env.local
cmp ../worktree-delivery/.env.local local-settings/delivery.env.local

При совпадении cmp завершится с кодом ноль и ничего не напечатает. Копия находится в первой рабочей папке, за пределами worktree-delivery. Для настоящих секретов выбирайте предусмотренное проектом защищённое место хранения.

После сохранения нужных файлов удалите второе дерево:

git worktree remove ../worktree-delivery
git worktree list

В списке останется исходная папка. Git откажет в удалении при изменениях отслеживаемых файлов или наличии неигнорируемых неотслеживаемых файлов. Игнорируемые файлы могут быть удалены вместе с деревом даже при чистом обычном status, поэтому его одного недостаточно.

После удаления дерева можно удалить ветку, уже вошедшую в текущий main:

git branch -d fix/delivery

Удаляйте рабочую папку и ветку отдельно. Если исправление ещё не принято, ветку можно оставить как ссылку на коммит, даже когда папка больше не нужна. Команда branch -d здесь безопаснее принудительного удаления: она проверяет условие объединения.

Не заменяйте git worktree remove удалением папки в файловом менеджере. Если папку уже удалили вручную, сначала посмотрите git worktree list, затем разберитесь с оставшейся служебной записью. git worktree prune --dry-run показывает кандидатов на очистку; исполнять очистку следует после проверки путей, особенно если дерево было на временно отключённом диске.

Сохраните чек-лист двух задач

Перед действиемЧто проверитьЗачем
Создать новое деревоstatus, worktree list, начальная веткаСохранить исходную задачу и выбрать правильную базу
Установить зависимостиТекущая папка, менеджер пакетов, файл блокировкиНе заменить окружение другой задачи
Запустить приложениеПорт и локальная конфигурацияОткрыть именно нужную ветку
Создать коммитdiff и diff --cachedЗафиксировать только исправление
Удалить деревоОбычный status, status --short --ignored, нужный коммит и копии локальных файлов вне удаляемой папкиСохранить работу и локальные настройки
Удалить веткуПринято ли изменение в нужную веткуСохранить ссылку на непринятый результат

Если исправление при объединении затронет тот же компонент, что и текущая задача, работа с конфликтом остаётся отдельной частью Git. Для сохранения поведения пригодится материал «Как разрешить конфликт в компоненте».

Для самостоятельной проверки вернитесь в feature/catalog и убедитесь, что строка «Раздел: атласы» сохранилась после всей работы с доставкой. Затем создайте ещё одно дерево для fix/title от main, измените заголовок каталога, сделайте коммит и удалите дерево только после проверки статуса. Ветка должна остаться видна в git branch, пока вы не решите её судьбу отдельно.

Повторите создание дерева для новой ветки и до удаления составьте карту двух рабочих деревьев. Укажите папки, текущие ветки, сохранённые изменения и общие ресурсы Git. Для портов и внешних данных запишите «в этом стенде не используются». Отдельно отметьте, где лежит копия локальной настройки и переживёт ли она удаление второй папки.

Для дальнейшей практики с Git и веб-разработкой можно выбрать подходящий раздел в интерактивных курсах HTML Academy. Следующую параллельную задачу начните с git worktree list и явного выбора начальной ветки.


«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.

ТелеграмПодкастБесплатные учебники