Статей на тему много, но, видимо, недостаточно: время от времени слышу от коллег (последние 10 лет, в 4-х разных компаниях):

  • «Не могу пошарить экран с кодом, у меня другая ветка сейчас».

  • «Не хочу переключать ветку, придется запускать кодогенерацию, у меня сбросятся build-файлы, потом это опять пересобирать!»

  • «Стаскивать ветку для просмотра ПР? Это же неудобно, надо "стэшить" изменения, ветку переключать».

  • «А я “склонировал“ 3 копии проекта, `git clone` to the rescue!»

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

Почему "древесные лягушки"? Всего лишь совпадение по слову “Tree“ в “Tree frogs“ и git worktree, о котором пойдет речь.

И последнее, если и так знаете про git worktree, предлагаю сразу перейти к разделу "Мой вариант использования git worktree".

О проблемах и “неправильных“ решениях

Во введении к статье было уже все сказано, но для формализма распишу еще раз.

Проблемы:

  1. Потеря текущих изменений кода при смене ветки;

  2. Потеря временных файлов кодогенерации/компиляции при смене ветки.

Решения:

  1. Временный коммит и смена ветки. Решает проблему 1;

  2. git stash и смена ветки. Решает проблему 1, но можно потеряться в стешах, если не давать им имена;

  3. git clone проекта в другую папку. Решает 1 и 2;

  4. git worktree проекта в другую папку. Решает 1 и 2.

Решение 3 содержит новые проблемы. Придется в каждом клоне проекта дублировать .git файлы — держать каждый проект в актуальном состоянии, вызывать git fetch для каждого, и т.д.

Решение 4 — то, которым я пользуюсь, и статья, по-существу, об этом.

Подробнее о “неправильных“ решениях

Оба решения (1 и 2 из раздела выше) подразумевают смену веток. Это может быть git checkout или git switch — попался коммент, рассказывающий о разнице подробнее, не хочу дублироваться.

Называю решения “неправильными“, имея в виду, что есть решение лучше. Лучше тем, что позволяет не терять файлы кодогенерации, кеши и прочие оптимизации систем сборки проекта. Слово “неправильные“ беру в кавычки, потому что не всегда все однозначно, и иногда `git stash` — лучшее решение, об этом будет ниже.

Решение с временным коммитом

Удобно делать коммит, а не stash, чтобы случайно не потерять изменения. У меня были случаи, когда вместо git stash pop вызывал git stash drop.Не смертельно, но повозиться с reflog придется.

Сперва коммитим все изменения

> git add -A && git commit -m 'tmp commit'

Затем переключаемся на другую ветку с git checkout <branch name>. Когда вернемся на изначальную ветку, нам может быть интересно, какие изменения были в 'tmp commit'.

> git show

Далее можем сделать "uncommit" командой git reset HEAD~1 --soft, либо добавить изменения в имеющийся коммит, изменив ему имя:

> git add -A
> git commit -m 'Fix all the release bugs, but introduce more' --amend

Решение с `git stash`

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

Пример использования stash без имени с удалением из стека:

> git stash

# переключается на другую ветку
> git checkout some-branch

# делаем что-то, что нужно в some-branch, и возвращаемся обратно
> git checkout -

# возвращаем то, что у нас было
> git stash pop

Пример с использованием имени в stash, поиск по имени, применением без удаления из стека (может быть нужно, чтобы не запутаться, когда пользуемся stash часто):

# создаем стеш с именем
> git stash push -m "trying to make something work"

# переключается на другую ветку
> git switch some-branch

# делаем что-то, что нужно в some-branch, и возвращаемся обратно
> git switch -

# смотрим стек стешей, копируем нужный
> git stash list
# смотрим его содержание, чтобы убедиться, что этот тот самый
> git show stash@{0}

# применяем stash, не удаляя его из стека
> git stash apply

Когда “неправильные“ решения — правильные?

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

Если у в проекте нет кодогенерации (или в конкретном случае она не понадобится) или чистая сборка проекта занимает считанные секунды, — оба решения также хороши.

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

Если же кодогенерация занимает несколько минут, а вам надо активно делать коммиты в разные ветки, для которых каждый раз нужен clean build, то удобно использовать git worktree.

О git worktree

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

— Что делает команда?
— Создает копию проекта. Копия смотрит на указанную ветку. Ветку можно поменять.

— Чем git worktree отличается от того, чтобы вызывать git clone с другим именем папки?
git worktree позволяет централизованно управлять репозиторием. Простыми словами: достаточно вызывать git fetch в любой папке, чтобы обновления были видны во всех.

Пример использования:

# переходим в папку с проектом
> cd ~/project

# создаем 2 копии для двух релизных веток
> git worktree add ../release1 release-branch1
> git worktree add ../release2 release-branch2

# проверяем, что все создалось
> git worktree list

~/project  d5e92f1 [master]
~/release1 9d77097 [release-branch1]
~/release2 8b2f312 [release-branch2]

Теперь в папках будут лежать копии проекта с соответствующей веткой.

  • Ок, а что насчет git clone --reference <project path> --dissociate?

  • Вкратце: с git clone --reference проще выстрелить себе в ногу, т.к. основной проект не знает о том, что какой-то клон меняет его файлы. Написана статья и про другие проблемы: git clone --reference Considered Harmful.

Мой вариант использования git worktree

О проблемах уже писал выше, поэтому спрячу.

Проблемы на текущем проекте, которые решаю с `git worktree`

На проекте часто приходится работать с тремя ветками, для каждой из которых нужна кодогенерация. Если сменить release-branch1 на release-branch2 или master, то нужно запустить clean build, который сломается с какой-то вероятностью, и нужно будет руками удалять build-папки или править что-то еще. Если не сломается, все равно придется ждать минут 5.

Кроме релизных есть ветки, где работаю над задачами, которые могут “черипикаться“ в другие ветки, несовместимые по файлам кодогенерации. Если не запускать кодогенерацию, IntellijIDEA подсветит часть файлов проекта красным. Иногда ничего страшно, да и тесты все равно пройдут на CI, но бывает, что нужно это запускать и дебажить.

Иногда хочется посмотреть ветку ПР локально и даже запустить, потому что так эффективнее и надежнее (IMHO). Опять же, не хочется тратить время на временные коммиты и потерю файлов кодогенерации.

Я всегда держу несколько папок с проектом по принадлежности к релизным веткам:

  1. master (основная ветка, новые релизы у нас отводятся от нее);

  2. release3 (новая релизная ветка — следующий релиз);

  3. release2 (предыдущая релизная ветка — релиз в процессе);

  4. release1 (самый старенький, удаляю его после того, как релиз2 “зарелизится“);

  5. master копия (в мастер всегда больше всего PR-ов, поэтому удобно иметь клон).

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

Пример

Делаю свою задачу в мастер, у меня открыт проект в папке master. Просят быстро сделать хотфикс в release2. Открываю проект в папке release2 и создаю там ветку: git checkout -b hotfix release2. Можно будет сразу запустить проект, минуя clean build. Не нужно суетиться, пряча свои текущие изменения в stash.

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

> git worktree add -b release1-2 ../release1-2 release-branch1
# сделать и запушить нужный мне фикс, а когда буду уверен, что папка больше не нужна,
# удалить папку, чтобы не копить мусор 
> git worktree remove ../release1-2

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

Проблемы при использовании git worktree

В общем-то, проблем никаких нет

Но могут быть мелкие неудобства:

  1. Лишнее место на диске.

  2. Нельзя "зачекаутить" одну и ту же ветку в двух worktree.

  3. Нельзя удалить ветку, если на нее смотрит какой-то из worktree. Гит об этом скажет, и тут просто надо удалить этот worktree (git worktree remove <path>).

  4. Могут быть проблемы в функционале недоделанных инструментов. Например, я когда-то отказывался от neovim-плагина neogit, потому что были баги в worktree (Github Issues: 1, 2). В комментарии к статье писали о проблемах с Eclipse и vscode devcontainers.

  5. Если используете `git submodule`, то в каждой папке worktree придется обновлять их отдельно. Обходные пути есть.

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

В заключение

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

Комментарии (57)


  1. MarijQA
    02.07.2024 17:10

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


    1. arturdumchev Автор
      02.07.2024 17:10
      +2

      Спасибо, поправил.


      1. MarijQA
        02.07.2024 17:10

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


  1. ishpartko
    02.07.2024 17:10
    +5

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


    1. arturdumchev Автор
      02.07.2024 17:10
      +1

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


  1. FreeNickname
    02.07.2024 17:10
    +2

    Эх, знал бы я об этом 2 часа назад) Спасибо!


    1. arturdumchev Автор
      02.07.2024 17:10

      `git stash drop` случайно сделали?)


      1. FreeNickname
        02.07.2024 17:10
        +1

        Я из тех самых людей, которые stash-ат и меняют ветку) Но там часть зависимостей не в гите, проект довольно старый, и нет уверенности, что они потом нормально подтянутся, и что я ничего не забыл)

        Правда, я ещё из тех мерзких людей, которые используют UI (SourceTree), не знаю, умеет ли он в worktree. Ну, есть только один способ проверить)) К тому же, всё равно часть приходится делать в консоли (например, на одном из проектов были теги с аннотациями). Плюс одно действие.


        1. mayorovp
          02.07.2024 17:10
          +2

          Переходите на винду, у нас есть Git Extensions

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


  1. dim_bug
    02.07.2024 17:10

    Дерево норм тема.


  1. qw1
    02.07.2024 17:10
    +2

    Ну очень не хватает возможности делать несколько копий одной ветки.
    Чтобы делать несколько фич параллельно и коммитить только те, которые готовы.


    1. arturdumchev Автор
      02.07.2024 17:10
      +1

      Чем не нравится вариант делать ветку A, а затем отводить от нее ветки А1, А2... Аn (можно с тем же worktree)? И когда они готовы, мержить их в А? Кажется, так проще будет самому не запутаться.


      1. qw1
        02.07.2024 17:10

        Если сделать ветку A от master, то git pull перестанет принимать в неё обновления из master.
        Вроде нашёл ключик --force для git worktree add, буду наблюдать, что из этого получится.


        1. encyclopedist
          02.07.2024 17:10
          +6

          Вы можете вручную задать upstream ветку origin/master для вашей рабочей ветки А:

          git branch --set-upstream-to=origin/master
          


          1. qw1
            02.07.2024 17:10

            Тогда это вообще прекрасно, если пуши будут попадать в master!


            1. FreeNickname
              02.07.2024 17:10
              +1

              А если и пуши в master, и pull из master-а, то чем это отличается просто от использования локальной ветки master, просто с другим названием? Не совсем понимаю.


              1. qw1
                02.07.2024 17:10
                +3

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


                1. FreeNickname
                  02.07.2024 17:10

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


    1. Fails
      02.07.2024 17:10

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


    1. Playa
      02.07.2024 17:10

      Попробуйте GitButler


      1. qw1
        02.07.2024 17:10

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


  1. BearOff
    02.07.2024 17:10
    +10

    Для справки:

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

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


  1. Tony-Sol
    02.07.2024 17:10

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


    1. arturdumchev Автор
      02.07.2024 17:10

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


  1. wl2776
    02.07.2024 17:10

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

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

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

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

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


  1. Deosis
    02.07.2024 17:10
    +1

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


    1. zuxul
      02.07.2024 17:10
      +3

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


    1. arturdumchev Автор
      02.07.2024 17:10

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


  1. ImagineTables
    02.07.2024 17:10
    +2

    А в черепахе это есть?


    1. AnyKey80lvl
      02.07.2024 17:10
      +5

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


      1. ImagineTables
        02.07.2024 17:10
        +3

        Как говорится, хочешь что-то узнать — узнай это сам: https://tortoisegit.org/docs/tortoisegit/tgit-dug-worktrees.html

        Прыгают. Но низэнько


  1. aamonster
    02.07.2024 17:10
    +1

    Хм, я вроде раньше пользовался (сэкономил на clone), но что-то не понравилось (уже не помню, что именно), и вернулся к варианту 3.

    Imho зря вы такой длинный текст для такой простой штуки раскатали. Сравнивать с вариантами 1 и 2 (временные ветки и stash) вообще бессмысленно, разработчики, которым они не подходят, и так знают об этом (например, мне надо открывать в xcode два разных воркспейса – для iOS и MacOS, но они имеют общие подпроекты утилит сборки, и XCode этого стерпеть уже не может). А сравнение со вторым клоном очень простое, одного-двух абзацев бы хватило.


    1. arturdumchev Автор
      02.07.2024 17:10
      +5

      зря вы такой длинный текст

      На всякий случай написал, чтобы и новичку было полезно и понятно все. Для пользователей вроде вас оставил во введении предложение сразу перескочить к разделу "Мой вариант использования git worktree".

      Сравнивать с вариантами 1 и 2 (временные ветки и stash) вообще бессмысленно, разработчики, которым они не подходят, и так знают об этом

      Как я в статье и сказал, последние 10 лет вижу, как люди буквально мучаются от того, что у них все тормозит, лагает, бесятся, что нужно clean build делать. Фразу о том, что человек не может показать код, потому что ему на ветку нужно прыгать, слышал не далее, как месяц назад. Я эту статью написал в том числе для того, чтобы коллегам скинуть. И все коллеги как раз 1 и 2 и используют.

      А сравнение со вторым клоном очень простое, одного-двух абзацев бы хватило.

      А разве у меня больше?


      1. aamonster
        02.07.2024 17:10
        +4

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


        1. arturdumchev Автор
          02.07.2024 17:10
          +2

          В мастер же обычно напрямую никто ничего не пушит. Вместо этого создают ветки от мастера и потому создают ПР в мастер. Можно создать ветку от мастера без чекаута на мастер:

          > git checkout -b feature1 master

          А если случайно "зачекаутились" от другой ветки, можно просто вернуть ее содержание на мастер:

          > git fetch # чтобы потом на свежий мастер обновиться
          > git reset --hard origin/master


          1. aamonster
            02.07.2024 17:10
            +1

            Если у вас с гитом работает небольшая команда – обычно людям дают самим мёржить ветки в мастер. А то и одиночные коммиты делать прямо в него.

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

            ЗЫ: При виде "git reset" до сих пор вздрагиваю, хотя много лет прошло... Мне в своё время пришлось освоить git reflog практически сразу: я как-то в hg привык, что ты не можешь в одно движение разломать себе репу.


            1. arturdumchev Автор
              02.07.2024 17:10

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

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


              1. aamonster
                02.07.2024 17:10

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

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


  1. AskePit
    02.07.2024 17:10
    +1

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

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

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

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


    1. Deosis
      02.07.2024 17:10
      +5

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

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


      1. AskePit
        02.07.2024 17:10

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


    1. arturdumchev Автор
      02.07.2024 17:10
      +1

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

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

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

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

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


      1. AskePit
        02.07.2024 17:10
        +1

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

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


    1. AskePit
      02.07.2024 17:10
      +1

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


  1. coctic
    02.07.2024 17:10
    +1

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

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

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


  1. korotky
    02.07.2024 17:10

    Amend, с одной m


    1. arturdumchev Автор
      02.07.2024 17:10

      Спасибо, исправил.


  1. Ashim96
    02.07.2024 17:10
    +2

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


  1. fishHook
    02.07.2024 17:10

    Я правильно понимаю, что нет какой-то "активной" версии кода когда используем деревья? Я имею в виду, когда я делаю чекаут на ветку, я получаю другую версию кода в той же самой директории. При этом моя ИДЕ остается открытой на том же проекте. А для того чтобы работать в стиле wortree мне надо для каждого дерева создавать проект в ИДЕ и деражть окрытыми несколько версий ИДЕ?


    1. qw1
      02.07.2024 17:10
      +1

      В этом и суть. Есть несколько "активных" веток. В каждой открыта своя IDE, можно компилировать, запускать, отлаживать сразу одновременно несколько фич. Чтобы не тратить время на восстановление контекста при возврате к предыдущей задаче.


      1. arturdumchev Автор
        02.07.2024 17:10

        Ага, IntellijIDEA пытается помогать, и когда в рамках одного проекта переключаешь ветку, то она открывает те же файлы, которые были открыты. Но все равно она восстанавливает не весь контекст, и может понадобиться clean build делать.

        Когда я в Neovim работал на Clojure-проекте, проблем открывать другую папку вообще не было, дело 200 мс. Сейчас на Java/Kotlin с IntellijIDEA. Открыть другой проект подольше, но жить можно.


    1. mayorovp
      02.07.2024 17:10

      Зачем создавать проект в IDE, когда надо просто открыть лежащий в репозитории?


  1. vic_1
    02.07.2024 17:10
    +1

    Ещё можно отмапить worktree на виртуальный диск чтобы пути в ide не менять


  1. lrrr11
    02.07.2024 17:10
    +1

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

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

    объяснение плохое и не отражающее сути.

    Суть в том, что git хранит содержимое всех файлов в хранилище объектов в папке .git, откуда распаковывает их в рабочую папку (worktree в их терминологии), по умолчанию - в родительскую по отношению к .git.

    Команда git clone копирует и рабочее дерево, и хранилище объектов.

    Команда git worktree копирует рабочее дерево, а хранилище объектов в целевой папке вместо копирования заменяет файлом со ссылкой на основное, экономя таким образом много места (т.к. хранилище объектов может сильно разрастаться в активных репозиториях. Кстати советую набрать git gc, чтобы освободить место)


    1. arturdumchev Автор
      02.07.2024 17:10
      +1

      объяснение плохое и не отражающее сути.

      Не соглашусь с вами. Моя статья о том, как и зачем пользовать worktree, а не о деталях реализации.

      Пользователя, который держит несколько "clone-ов" проекта, проще убедить фразой "достаточно вызывать git fetch в любой папке, чтобы обновления были видны во всех", чем вашими тремя абзацами, которые он с большей вероятностью пропустит, читая статью по диагонали.


  1. AMDmi3
    02.07.2024 17:10
    +3

    git diff $(git rev-parse HEAD)^

    Зачем такая сложность? Можно git diff HEAD^, а вообще просто git show


    1. arturdumchev Автор
      02.07.2024 17:10

      Вы правы. У меня остался алиас с незапамятных времён. Поправлю в статье.