lesson ── git-labs ── ~18 мин ── 7 шагов
Цель - решить классическую задачу «делаю фичу, прилетел hotfix» без
stash. git worktree add создаёт второй working tree от того же
репозитория. Делаешь hotfix в одной директории, потом возвращаешься
в основную - и твоя фича на месте.
интерактивный sandbox
Поднимется контейнер gitlab/git-base с git, bash, pre-commit. В браузере откроется терминал, можно сразу git init. Каждый шаг проверяется автоматически. Сеть air-gapped, github.com недоступен.
stack ── git · bash · 256 MB RAM · air-gapped · самоуничтожается через 30 мин простоя
cd /home/student/work
mkdir -p worktree-lab && cd worktree-lab
git init -b main
echo "stable" > prod.txt
git add . && git commit -m "init: prod baseline"
git switch -c feat/big-refactor
echo "wip stage 1" > refactor.txt
git add . && git commit -m "wip: stage 1"
echo "wip stage 2" >> refactor.txt
git status
Сейчас ты на feat/big-refactor, есть один коммит и uncommitted работа в refactor.txt. Имитируем прерывание.
✓ Фича в работе, есть uncommitted изменения.
cd /home/student/work/worktree-lab
# worktree add <path> <branch>: создать второй working tree на ветке main
git worktree add ../wt-hotfix main
git worktree list # видишь оба tree, их пути и ветки
Появилась директория ../wt-hotfix. Это второй working tree,
его HEAD на main. Главный worktree (с твоей фичей) не тронут.
✓ Второй worktree создан. Один .git/, два tree.
cd /home/student/work/wt-hotfix # переходим во второй worktree
git status # на ветке main, working tree чист
echo "fixed" >> prod.txt
git commit -am "fix: critical issue in prod"
git log --oneline
Ты сейчас в wt-hotfix/, на ветке main. Сделал коммит, он
ушёл в main. В основном worktree фича всё ещё в работе,
uncommitted.
✓ Hotfix закоммичен в main, без stash, без переключения.
cd /home/student/work/worktree-lab
git rev-parse --abbrev-ref HEAD # --abbrev-ref = имя текущей ветки, не SHA
cat refactor.txt # обе строки на месте
git status # uncommitted stage 2 не пропал
git log --oneline --graph --all
Ветка - всё ещё feat/big-refactor. refactor.txt содержит
обе строки (stage 1 + uncommitted stage 2). Граф показывает:
на main коммит fix: critical issue, а твоя ветка от него
отдельно.
✓ Фича цела. Ничего не потерялось.
cd /home/student/work/worktree-lab
git worktree remove ../wt-hotfix # удалить worktree (директорию + регистрацию)
git worktree list # снова один tree
ls /home/student/work/ | grep wt-hotfix && echo "still there" || echo "removed"
Worktree удалён. .git/ остался один, объекты сохранены, ветка
main - тоже сохранена с твоим hotfix-коммитом.
✓ Worktree удалён. История hotfix в main сохранена.
Git разрешает один worktree на ветку. Иначе получились бы две «активные» копии одного состояния, и непонятно, где источник.
cd /home/student/work/worktree-lab
git worktree add ../wt-fail feat/big-refactor # упадёт: ветка уже занята main worktree
Должен упасть с fatal: 'feat/big-refactor' is already used by worktree at .... Это защита, не баг.
Если правда нужна вторая копия - делай новую ветку:
# -b <new> = создать новую ветку из <start-point>, чтобы обойти конфликт
git worktree add -b feat/big-refactor-test ../wt-test feat/big-refactor
git worktree list
git worktree remove ../wt-test
Команда падает - это правильное поведение. Дальше используй `-b new-name`.
✓ Защита Git увидена, обходной путь известен.
cd /home/student/work/worktree-lab
git add refactor.txt
git commit -m "feat: complete refactor"
git switch main
# --no-ff = всегда merge-коммит, чтобы было видно границу фичи в логе
git merge --no-ff feat/big-refactor -m "merge refactor"
git log --oneline --graph --all
Финальный граф: main содержит hotfix и refactor, оба слиты по отдельности. Это сценарий, где worktree сэкономил время: ты не переключал контекст, не stash'ил, не терял ничего.
✓ Hotfix и фича в main. Параллельная работа без stash отработана.
git worktree add создаёт второй working tree рядом с основным.
Оба смотрят в один .git/. Удаляется через worktree remove.
Не stash, а полноценный второй workspace.
команды
git worktree add ../hotfix mainсоздать второй working tree на ветке maingit worktree listувидеть все worktree этого репоgit worktree remove ../hotfixудалить worktreegit worktree pruneвычистить запись о вручную удалённом worktreeконцепции