Свободно экспериментируйте над кодом с Git worktree

Источник: «Experiment on your code freely with Git worktree»
Получите свободу в экспериментах, а также уверенность в том, что есть новый, связанный клон репозитория, если эксперимент пойдёт не так.

Git создан отчасти для того, чтобы позволить экспериментировать. Когда вы знаете, что работа надёжно отслеживается и есть безопасные состояния, на которые можно опереться, если что-то пойдёт не так, вы не боитесь пробовать новые идеи. Однако цена инноваций заключается в том, что в процессе работы, скорее всего, возникнет беспорядок. Файлы переименовываются, перемещаются, удаляются, изменяются и разрезаются на части. Появляются новые файлы. Временные файлы, которые не нужно отслеживать, поселяются в рабочем каталоге.

Короче говоря, ваше рабочее пространство превращается в карточный домик, шатко балансирующий между оно почти работает! и о нет, что я наделал?. Что же делать, если необходимо вернуть репозиторий в известное состояние на полдня, чтобы можно было заняться реальной работой? На ум сразу приходят классические команды git branch и git stash, но ни одна из них так или иначе не предназначена для работы с неотслеживаемыми файлами, а изменившиеся пути к файлам и другие серьёзные изменения могут привести к тому, что просто откладывать работу на потом будет неудобно. Ответ — Git worktree.

Что такое Git worktree

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

Канонический пример, взятый прямо с man-страницы git-worktree: вы работаете над новой интересной фичей проекта, когда менеджер проекта сообщает, что требуется срочное исправление. Проблема в том, что ваш рабочий репозиторий (ваше "worktree"/рабочее дерево) находится в беспорядке, потому что вы разрабатываете важную новую фичу. Вы не хотите "протаскивать" исправление в текущий спринт, и вам неудобно создавать новую ветку для исправления. Вместо этого вы решаете создать новое рабочее дерево, для внесения в него исправления:

git branch | tee
* dev
trunk
git worktree add -b hotfix ~/code/hotfix trunk
Preparing ../hotfix (identifier hotfix)
HEAD is now at 62a2daf commit

Теперь в каталоге code есть новый каталог hotfix, являющийся Git worktree, связанным с основным репозиторием проекта, с HEAD в ветви под названием trunk. Теперь можно обращаться с этим рабочим деревом так, как если бы оно было основным рабочим пространством. Вы можете сменить в нем каталог, внести срочное исправление, закоммитить его и, в конце концов, удалить рабочее дерево:

cd ~/code/hotfix
sed -i 's/teh/the/' hello.txt
git commit --all --message 'urgent hot fix'

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

git push origin HEAD
cd ~/code/myproject

Или можно заархивировать рабочее дерево в файл TAR или ZIP:

cd ~/code/myproject
git archive --format tar --output hotfix.tar master

Или можно получить изменения локально из отдельного рабочего дерева:

git worktree list
/home/seth/code/myproject 15fca84 [dev]
/home/seth/code/hotfix 09e585d [master]

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

Список активных рабочих деревьев

Вы можете получить список рабочих деревьев и посмотреть, какая ветвь была загружена в каждом из них, с помощью команды git worktree list:

git worktree list
/home/seth/code/myproject 15fca84 [dev]
/home/seth/code/hotfix 09e585d [master]

Это можно использовать из любого рабочего дерева. Рабочие деревья всегда связаны (если только не переместить их вручную, что нарушает способность Git'а определять местоположение рабочего дерева и, следовательно, разрывает связь).

Перемещение рабочего дерева

Git отслеживает местоположение и состояние рабочего дерева в каталоге .git проекта:

cat ~/code/myproject/.git/worktrees/hotfix/gitdir
/home/seth/code/hotfix/.git

Если необходимо переместить рабочее дерево, это нужно делать с помощью git worktree move; в противном случае, когда Git попытается обновить статус рабочего дерева, он потерпит неудачу:

mkdir ~/Temp
git worktree move hotfix ~/Temp
git worktree list
/home/seth/code/myproject 15fca84 [dev]
/home/seth/Temp/hotfix 09e585d [master]

Удаление рабочего дерева

Когда работа будет закончена, удалить рабочее дерево можно с помощью команды git worktree remove:

git worktree remove hotfix
git worktree list
/home/seth/code/myproject 15fca84 [dev]

Чтобы убедиться, что каталог .git чист, используйте команду git worktree prune после удаления рабочего дерева:

git worktree prune

Когда использовать Git worktree

Как и в случае со многими другими опциями, будь то закладки или автоматическое резервное копирование, вы сами должны следить за генерируемыми данными, иначе они могут стать непомерно большими. Не используйте рабочие деревья слишком часто, чтобы не получилось 20 копий репозитория, каждая из которых находится в несколько ином состоянии. Я считаю, что лучше всего создать рабочее дерево, выполнить задачу, которая его требует, закоммитить работу, а затем удалить дерево. Всё должно быть просто и сконцентрировано.

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

Дополнительные материалы

Предыдущая Статья

Совет по безопасности: Увеличьте раунды bcrypt

Следующая Статья

Laravel Фасады — Пишем тестируемый код