Pull to refresh

Comments 71

И всё-таки worktree или wortree?

Пожалуйста, я уж думала, что я чего-то не понимаю))

Не совсем понимаю, почему минусят коммент с отметкой опечатки. Кто-нибудь может объяснить, что ужасного в нём? Притом что и карме досталось. Разве есть возможность как-то лично автору сообщить, что в тексте ошибка? Подскажите новенькой, пожалуйста!

С компьютера — выделить проблемное место, нажать Ctrl-Enter, будет окошко для отправки замечания непосредственно автору. Как это делать с мобильных устройств — не знаю.

Спасибо.

UFO just landed and posted this here

Наверно 🤦🏼‍♀️ спасибо за ответ

Спасибо добрый человек, я как раз пилю гуи для этой цели в компании(надо много линковать+микрофронты), очень облегчит дело

Спасибо за обратную связь! Уверен, с worktree будет удобно

Эх, знал бы я об этом 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, просто с другим названием? Не совсем понимаю.

Раньше я делал несколько копий репозитория, в каждой копии пилил какую-то фичу и пушил по мере готовности. worktree позволит иметь один репозиторий, экономя на повторах папки .git, а также fetch можно делать единожды, он затронет все копии.

А, кажется, понял. Спасибо)

git worktree add <path> --detach <branch_name>

Попробуйте GitButler

Посмотрел их презенташку. Мне кажется, мне это не нужно - управлять каждым минимальным изменением в файлах. Это хорошо, когда примеры простенькие - "поменял цвет фона" - изменение в единственной строчке. Если же одно изменение это 15 мест в разных файлах, а другое изменение 20 мест в файлах, частично пересекающихся с первыми, получается какой-то микро-менеджмент изменений.

Для справки:

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

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

Давненько приглядывался к worktree, но не могу заставить себя попробовать - как-то всегда хватало stash/временный commit/diff > apply

Может быть, жизнь заставит, если придется работать над 3-4 задачами условно одновременно. Если в дополнении к этому окажется, что чистая сборка 30 минут (такое тоже было), то тут только копии (worktree) проекта держать.

Один из долгих этапов сборки может быть скачивание всех зависимостей.

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

Только ситуация с хотфиксами требует создания "копиии" резитория. У нас сложный процесс на этот счёт и мы делаем всё в новой папке. Правда мы используем не git clone, а самописный инструмент.

Только ситуация с хотфиксами требует создания "копиии" резитория.

Вот ту же как раз worktree и подходит.

Правда мы используем не git clone, а самописный инструмент.

А почему так? Git worktree еще не было на момент, когда проблема появилась?

Попробую объяснить нашу систему, хотя сам не до конца всё понимаю и не часто использую.

Если кратко то это виртуальная монорепа.

Поддерживаются несколько языков (С#, Java, Python, Javascript/Typescript)

Для быстрой разработки было принято решение не указывать версии зависимостей внутри приложения. Вы собираете приложение с самой свежей версией внутренних зависимостей.

Чтобы это работало придуман собственный инструментарий (на базе gradle).

Вы создаёте workspace и туда клонируете свои репозитории. Когда вы собираете проект, то если зависимость склонирована, то она тоже будет собрана из исходников , а если нет то скачается версия с билд системы. В момент создания актуальный build_id прописывается в папку с репозиториями.

Есть команда refresh которая подтянет мастер в репозитории и пропишет последний build_id

Для хотфиксов процесс такой-же как для разработки, только вместо gradle init используется gradle hotfix <build_id>.

Переделать на git worktree наверно можно, но это требует ресурсов.

Надо будет попробовать.

Обучаю нейросети, код храню в git. Стараюсь хранить все эксперименты, один эксперимент - один коммит.

Бывают сложности, если есть очередь из задач на обучение. Код для задачи берётся из рабочего каталога, и может так получиться, что когда она попадёт на исполнение, там заcheckoutен уже не тот коммит.

Пока решаю эту проблему с помощью python executable zip archives

Docker по независящим от меня причинам использовать не могу.

Ещё один минус: не поддерживаются подмодули

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

Спасибо, добавлю к статье.

Черепахи в прыжках по веткам замечены не были

Хм, я вроде раньше пользовался (сэкономил на 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 привык, что ты не можешь в одно движение разломать себе репу.

Понимаю :) Ну вот когда нельзя в мастере ничего менять (у нас нельзя кстати, как и в релизных ветках), а только в ветках, над которыми работаешь локально, "git reset" использовать не страшно.

Я кстати когда над своими проектами работаю, не ставлю никакие запреты, но и --hard не использую никогда. Если коммит убрать, то спокойно revert, реже rebase. Пусть все будет в истории, не помешает.

Свои изменения потерять тоже жалко :-)

Это теперь я учёный и перед git reset новую ветку делаю, чтобы в случае чего с reflog не возиться.

В JetBrains иде есть локальная история, много раз меня спасала.

обычно людям дают самим мёржить ветки в мастер

У нас компания имеет требования по безопастности, любой код который идёт в прод, должен быть посмотрен вторым человеком.

А еще когда мерджи напримую запрещены и есть CI, то не придётся чинить тесты за того парня.

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

Если такое происходит часто, особенно в маленькой команде, то стоит подумать над процессами. Частые переключения до добра не доводят.

А вот в моем случае, например, worktree скорее дает меньше маневра, нежели второй честно откопированный репозиторий.

Рабочий проект весит больше полутерабайта, которые примерно пополам разделены между .git и остальной частью репо. Вот и выходит, что каждый раз, когда мне нужно создать worktree, у меня начинается копирование ~300Gb, и это занимает катастрофическое время. Ни о какой скорости и продуктивности для хотфикса и речи нет. Вот буквально вчера попробовал и на n-ой минуте тщательного копирования файликов гитом я просто прервал создание worktree.

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

Да, это занимает уйму места, но что поделать.

Ветка меняется как обычно.

Из ограничений: нельзя удалить ветку, на которую ссылается дерево.

оу, тогда это меняет дело! беглый гуглеж не дал мне таких ответов, а проверить самому как-то не пришлось

А так как (если я конечно все правильно понял), worktree намертво привязан к одной ветке

Ветку в каждом worktree можно поменять, точно так же как меняешь в копии проекта, которую "склонил". Разница только в том, что папка.git будет общей, т.е. только в одном проекте достаточно сделать `git fetch`. И нельзя одну и ту же ветку в держать в основном проекте и в worktree.

Кстати, по поводу того, что .git 300gb. Если большая история, можно сэкономить, не держа все изменения за все времена.

> git clone --depth 300 <project url>.

Команда выше заберет только последние 300 коммитов.

Что же, значит я действительно не так понял worktree. Попробую улучшить качество жизни сегодня же :)

За хинт с ограниченной историей тоже спасибо, думаю, это должно освободить приличное количество места

В общем, спасибо @Deosis и @arturdumchev за наводки. Мои предположения о несменяемости ветки в worktree были неверны. Теперь я тоже перешел на git worktree и, добавив дополнительный флаг --ignore-other-worktrees к алиасу для команды git checkout, могу делать все то же, что делал раньше с полноценным клоном репозитория, но с меньшим количеством занятого места

Касаемо больших репозиториев, советую глянуть это видео (да и помимо этого много интересного там можете найти).

Проблемы git worktree есть (частные но тем не менее):

Eclipse не умеет с ними работать. Соответственно, если разработка в eclipse - вся работа с git уходит в ком. строку. Вообще вся, даже diff не посмотреть. Eclipse не понимает, что это репозиторий.

vscode devcontainers. Если .devcontainer в репозитории, то в контейнере открывается одно worktree, и там внезапно не оказывается основного репозитория, и работа git тоже ломается. Надо городить костыли с другой точкой монтирования. Я пока не нашел разумного решения.

Сколько ж Миша-часов могло быть сэкономлено... Спасибо за статью!

Я правильно понимаю, что нет какой-то "активной" версии кода когда используем деревья? Я имею в виду, когда я делаю чекаут на ветку, я получаю другую версию кода в той же самой директории. При этом моя ИДЕ остается открытой на том же проекте. А для того чтобы работать в стиле 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 на проектах, не везде тестеров допускают к нему. Хотя по-моему зря. Практический опыт гораздо лучше глухой теории. С интересом прочитала комментарии, думаю, это скажется на общении с нашими разработчиками))

Если не запускать кодогенерацию, IntellijIDEA подсветит часть файлов проекта красным.

Знакомая проблема. Что думаете насчет добавления генеренного кода в git-репо (тогда и при смене веток генеренный код соответственно переключался)?
Я поначалу был категорично настроен по отношению к этой идее, но на практике оказалось весьма неплохо в т.ч. и потому, что это позволяло видеть изменения в истории не только в исходниках кодогенерации (вроде proto-файлов или SQL-миграций), но и в генеренном коде. Тут, конечно, это не для всех случаев подойдет, но для многих - как минимум, это позволит делать компиляцию средствами IDE без необходимости делегирования в build-систему. А это, между прочим, означает эффективную инкрементную сборку. Проще и быстрее.
Тема дискуссионная и здесь, конечно, есть подводные камни.

Плюсы есть, но я бы так не стал делать, потому что:
- билд-файлы могут отличаться в зависимости от операционной системы, версии системы сборки, версии языка и прочего, что локально по разным причинам может отличаться.
- На CI могут возникнуть баги, если там другая ОС. Если на CI чистить билд-файлы и пересобирать, то иногда будут проблемы с тем, что вроде локально все проверил, а сборка на CI упала.
- Cгенерированный файлы могут много весить — кажется, “некрасиво“ хранить, пушить и пуллить их.
- Конфликтов будет больше, сложно мержить, если придется делать черипики. Например, придется даже для простых черипиков мержить все конфликты, кроме кодгенерации, а для остального собирать локально сборку, чтобы поправить генерацию.
- Стоит ли смотреть в ПР-ах билд-файлы (может отвлекать).

Для меня, как я в статье написал, worktree решает проблему.

Sign up to leave a comment.

Articles