Комментарии 55
И всё-таки worktree или wortree?
Спасибо добрый человек, я как раз пилю гуи для этой цели в компании(надо много линковать+микрофронты), очень облегчит дело
Эх, знал бы я об этом 2 часа назад) Спасибо!
`git stash drop` случайно сделали?)
Я из тех самых людей, которые stash-ат и меняют ветку) Но там часть зависимостей не в гите, проект довольно старый, и нет уверенности, что они потом нормально подтянутся, и что я ничего не забыл)
Правда, я ещё из тех мерзких людей, которые используют UI (SourceTree), не знаю, умеет ли он в worktree. Ну, есть только один способ проверить)) К тому же, всё равно часть приходится делать в консоли (например, на одном из проектов были теги с аннотациями). Плюс одно действие.
Переходите на винду, у нас есть Git Extensions
А если серьёзно, то, судя по скриншотам, теги с аннотациями SourceTree поддерживает, ради них точно нет смысла возвращаться в терминал. Что же до worktree - многие (но, увы, не все) программы прекрасно работают с ними если открыть заранее созданный worktree как отдельный репозиторий.
Дерево норм тема.
Ну очень не хватает возможности делать несколько копий одной ветки.
Чтобы делать несколько фич параллельно и коммитить только те, которые готовы.
Чем не нравится вариант делать ветку A, а затем отводить от нее ветки А1, А2... Аn (можно с тем же worktree)? И когда они готовы, мержить их в А? Кажется, так проще будет самому не запутаться.
Если сделать ветку A от master, то git pull перестанет принимать в неё обновления из master.
Вроде нашёл ключик --force
для git worktree add
, буду наблюдать, что из этого получится.
Вы можете вручную задать upstream ветку origin/master для вашей рабочей ветки А:
git branch --set-upstream-to=origin/master
Тогда это вообще прекрасно, если пуши будут попадать в master!
А если и пуши в master, и pull из master-а, то чем это отличается просто от использования локальной ветки master, просто с другим названием? Не совсем понимаю.
git worktree add <path> --detach <branch_name>
Попробуйте GitButler
Посмотрел их презенташку. Мне кажется, мне это не нужно - управлять каждым минимальным изменением в файлах. Это хорошо, когда примеры простенькие - "поменял цвет фона" - изменение в единственной строчке. Если же одно изменение это 15 мест в разных файлах, а другое изменение 20 мест в файлах, частично пересекающихся с первыми, получается какой-то микро-менеджмент изменений.
Для справки:
Прыгают древолазы редко, только в случае крайней необходимости, предпочитая передвигаться пешком.
Не способен прыгать с дерева на дерево, поэтому спускается на землю и переходит на другое дерево.
Давненько приглядывался к worktree, но не могу заставить себя попробовать - как-то всегда хватало stash/временный commit/diff > apply
Надо будет попробовать.
Обучаю нейросети, код храню в git. Стараюсь хранить все эксперименты, один эксперимент - один коммит.
Бывают сложности, если есть очередь из задач на обучение. Код для задачи берётся из рабочего каталога, и может так получиться, что когда она попадёт на исполнение, там заcheckoutен уже не тот коммит.
Пока решаю эту проблему с помощью python executable zip archives
Docker по независящим от меня причинам использовать не могу.
Ещё один минус: не поддерживаются подмодули
А в черепахе это есть?
Черепахи в прыжках по веткам замечены не были
Как говорится, хочешь что-то узнать — узнай это сам: https://tortoisegit.org/docs/tortoisegit/tgit-dug-worktrees.html
Прыгают. Но низэнько…
Хм, я вроде раньше пользовался (сэкономил на clone), но что-то не понравилось (уже не помню, что именно), и вернулся к варианту 3.
Imho зря вы такой длинный текст для такой простой штуки раскатали. Сравнивать с вариантами 1 и 2 (временные ветки и stash) вообще бессмысленно, разработчики, которым они не подходят, и так знают об этом (например, мне надо открывать в xcode два разных воркспейса – для iOS и MacOS, но они имеют общие подпроекты утилит сборки, и XCode этого стерпеть уже не может). А сравнение со вторым клоном очень простое, одного-двух абзацев бы хватило.
зря вы такой длинный текст
На всякий случай написал, чтобы и новичку было полезно и понятно все. Для пользователей вроде вас оставил во введении предложение сразу перескочить к разделу "Мой вариант использования git worktree".
Сравнивать с вариантами 1 и 2 (временные ветки и stash) вообще бессмысленно, разработчики, которым они не подходят, и так знают об этом
Как я в статье и сказал, последние 10 лет вижу, как люди буквально мучаются от того, что у них все тормозит, лагает, бесятся, что нужно clean build делать. Фразу о том, что человек не может показать код, потому что ему на ветку нужно прыгать, слышал не далее, как месяц назад. Я эту статью написал в том числе для того, чтобы коллегам скинуть. И все коллеги как раз 1 и 2 и используют.
А сравнение со вторым клоном очень простое, одного-двух абзацев бы хватило.
А разве у меня больше?
Вспомнил, кстати, что меня раздражало в worktree. Именно невозможность зачекаутить одну ветку в двух местах – что делало мёржи в мастер довольно неудобными. Тут в комментах как раз обсудили, как обойти это ограничение, так что, возможно, при очередной настройке рабочего места попробую вновь.
В мастер же обычно напрямую никто ничего не пушит. Вместо этого создают ветки от мастера и потому создают ПР в мастер. Можно создать ветку от мастера без чекаута на мастер:
> git checkout -b feature1 master
А если случайно "зачекаутились" от другой ветки, можно просто вернуть ее содержание на мастер:
> git fetch # чтобы потом на свежий мастер обновиться
> git reset --hard origin/master
Если у вас с гитом работает небольшая команда – обычно людям дают самим мёржить ветки в мастер. А то и одиночные коммиты делать прямо в него.
Да и просто перед созданием ветки – обычно переключаешься на мастер и делаешь pull. Вот тут-то и выяснялось, что переключиться на мастер ты не можешь, потому что утром уже сделал это в другой папке.
ЗЫ: При виде "git reset" до сих пор вздрагиваю, хотя много лет прошло... Мне в своё время пришлось освоить git reflog практически сразу: я как-то в hg привык, что ты не можешь в одно движение разломать себе репу.
А вот в моем случае, например, worktree скорее дает меньше маневра, нежели второй честно откопированный репозиторий.
Рабочий проект весит больше полутерабайта, которые примерно пополам разделены между .git
и остальной частью репо. Вот и выходит, что каждый раз, когда мне нужно создать worktree
, у меня начинается копирование ~300Gb, и это занимает катастрофическое время. Ни о какой скорости и продуктивности для хотфикса и речи нет. Вот буквально вчера попробовал и на n-ой минуте тщательного копирования файликов гитом я просто прервал создание worktree
.
А так как (если я конечно все правильно понял), worktree
намертво привязан к одной ветке, то мне сильно дешевле просто иметь второй клон репо, который будет выкачан единожды, но теперь у меня в распоряжении есть два репо, где я могу прыгать между любыми двумя ветками, как бабуин, без ограничений.
Да, это занимает уйму места, но что поделать.
Ветка меняется как обычно.
Из ограничений: нельзя удалить ветку, на которую ссылается дерево.
А так как (если я конечно все правильно понял),
worktree
намертво привязан к одной ветке
Ветку в каждом worktree можно поменять, точно так же как меняешь в копии проекта, которую "склонил". Разница только в том, что папка.git
будет общей, т.е. только в одном проекте достаточно сделать `git fetch`. И нельзя одну и ту же ветку в держать в основном проекте и в worktree.
Кстати, по поводу того, что .git 300gb. Если большая история, можно сэкономить, не держа все изменения за все времена.
> git clone --depth 300 <project url>.
Команда выше заберет только последние 300 коммитов.
В общем, спасибо @Deosis и @arturdumchev за наводки. Мои предположения о несменяемости ветки в worktree были неверны. Теперь я тоже перешел на git worktree
и, добавив дополнительный флаг --ignore-other-worktrees
к алиасу для команды git checkout
, могу делать все то же, что делал раньше с полноценным клоном репозитория, но с меньшим количеством занятого места
Проблемы git worktree есть (частные но тем не менее):
Eclipse не умеет с ними работать. Соответственно, если разработка в eclipse - вся работа с git уходит в ком. строку. Вообще вся, даже diff не посмотреть. Eclipse не понимает, что это репозиторий.
vscode devcontainers. Если .devcontainer в репозитории, то в контейнере открывается одно worktree, и там внезапно не оказывается основного репозитория, и работа git тоже ломается. Надо городить костыли с другой точкой монтирования. Я пока не нашел разумного решения.
Amend, с одной m
Сколько ж Миша-часов могло быть сэкономлено... Спасибо за статью!
Я правильно понимаю, что нет какой-то "активной" версии кода когда используем деревья? Я имею в виду, когда я делаю чекаут на ветку, я получаю другую версию кода в той же самой директории. При этом моя ИДЕ остается открытой на том же проекте. А для того чтобы работать в стиле wortree мне надо для каждого дерева создавать проект в ИДЕ и деражть окрытыми несколько версий ИДЕ?
В этом и суть. Есть несколько "активных" веток. В каждой открыта своя IDE, можно компилировать, запускать, отлаживать сразу одновременно несколько фич. Чтобы не тратить время на восстановление контекста при возврате к предыдущей задаче.
Ага, IntellijIDEA пытается помогать, и когда в рамках одного проекта переключаешь ветку, то она открывает те же файлы, которые были открыты. Но все равно она восстанавливает не весь контекст, и может понадобиться clean build делать.
Когда я в Neovim работал на Clojure-проекте, проблем открывать другую папку вообще не было, дело 200 мс. Сейчас на Java/Kotlin с IntellijIDEA. Открыть другой проект подольше, но жить можно.
Зачем создавать проект в IDE, когда надо просто открыть лежащий в репозитории?
Ещё можно отмапить worktree на виртуальный диск чтобы пути в ide не менять
Чем git worktree отличается от того, чтобы вызывать git clone с другим именем папки?
git worktree позволяет централизованно управлять репозиторием. Простыми словами: достаточно вызывать git fetch в любой папке, чтобы обновления были видны во всех.
объяснение плохое и не отражающее сути.
Суть в том, что git хранит содержимое всех файлов в хранилище объектов в папке .git
, откуда распаковывает их в рабочую папку (worktree
в их терминологии), по умолчанию - в родительскую по отношению к .git
.
Команда git clone
копирует и рабочее дерево, и хранилище объектов.
Команда git worktree
копирует рабочее дерево, а хранилище объектов в целевой папке вместо копирования заменяет файлом со ссылкой на основное, экономя таким образом много места (т.к. хранилище объектов может сильно разрастаться в активных репозиториях. Кстати советую набрать git gc
, чтобы освободить место)
объяснение плохое и не отражающее сути.
Не соглашусь с вами. Моя статья о том, как и зачем пользовать worktree, а не о деталях реализации.
Пользователя, который держит несколько "clone-ов" проекта, проще убедить фразой "достаточно вызывать git fetch в любой папке, чтобы обновления были видны во всех", чем вашими тремя абзацами, которые он с большей вероятностью пропустит, читая статью по диагонали.
git diff $(git rev-parse HEAD)^
Зачем такая сложность? Можно git diff HEAD^
, а вообще просто git show
Git. Скачем между ветками как древесные лягушки