В чем разница между git-worktree и git-subtree?

Когда я подумал, что Git уже не может быть сложнее, я открыл для себя git worktree. Либо это синоним поддерева, либо функция, о которой я никогда не знал. Рабочее дерево такое же, как поддерево, или они разные. Если они разные, то чем они отличаются и какую проблему решает worktree?


person ATL_DEV    schedule 11.02.2019    source источник
comment
С чего ты взял, что они одинаковы? Это совершенно разные команды. Это все равно, что спрашивать разницу между моржовой ручкой и шариковой ручкой. Нет краткого способа обсудить различия, кроме чтения о том, что они are. После того, как вы это сделаете, если вы все еще в замешательстве, вернитесь и задайте более конкретный вопрос.   -  person Chris    schedule 11.02.2019


Ответы (2)


Они очень разные. Чтобы понять их правильно, давайте определим work-tree (или "рабочее дерево", или "рабочее дерево", или почти любой вариант этих написаний) относительно индекса. и фиксировать.

Вы уже знаете, что коммиты сохраняют моментальные снимки и что каждая фиксация имеет уникальный хэш-идентификатор, который называет эту конкретную фиксацию. Может быть много других имен (например, имена веток и/или тегов) для одного и того же коммита, но есть только один хэш-идентификатор. Вы, вероятно, также знаете, что у коммитов есть метаданные: кто их сделал (имя и адрес электронной почты), когда (отметка времени) и почему (сообщение для git log для отображения). Каждая фиксация также имеет хэш-идентификатор parent — или, скорее, список родителей, обычно с одной записью. Родительский коммит — это коммит, который идет непосредственно перед этим, чтобы Git мог пройти в обратном направлении по цепочке коммитов, чтобы показать что-то с течением времени. (Фиксация с двумя родительскими хэш-идентификаторами называется объединенной фиксацией. Фиксация без отсутствия родительских хэш-идентификаторов является корневой фиксацией, и хотя бы один в любом непустом репозитории, поскольку перед первым коммитом не было коммитов.)

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

Это означает, что все файлы, хранящиеся внутри любого коммита, замораживаются. Они также сжаты в специальный формат только для Git, который может прочитать только Git. Это отлично подходит для истории, но как мы когда-нибудь закончим работу? Здесь на сцену выходит рабочее дерево.

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

Таким образом, между текущим коммитом (выбранным) и рабочим деревом есть две копии каждого файла: замороженная копия в коммите и полезная копия в дерево работы.

На этом можно было бы остановиться на Git и других системах контроля версий, таких как Mercurial (см. mercurial) сделайте именно это. Но по разным причинам (многие из них связаны с «очень быстрой работой») Git добавляет третью копию каждого файла. Эта третья копия попадает в то, что Git называет по-разному: индекс, индекс или кеш. (Какое имя вы видите, зависит от того, кто или какая часть Git выполняет вызов.) Файлы в индексе имеют почти ту же форму, что и в коммитах, за исключением того, что в индексе они не замороженный. Они более готовы к заморозке или «слякоти», если хотите.

Индекс также хранит вкладки в рабочем дереве, так что они тесно связаны друг с другом: индекс «знает», что находится в рабочем дереве, а если нет — если аспект кэширования индекса устарел — он знает это, что помогает Git быстро выяснить, что изменилось, если что-то изменилось. Более того, когда вы запускаете git commit, Git даже не просматривает рабочее дерево (кроме добавления комментариев к файлу, который вы будете редактировать для сообщения журнала). Он просто замораживает готовые файлы из индекса, где индекс получает свое имя staging area, чтобы сделать новую фиксацию.

В конце концов, когда вы работаете с фиксацией в Git, у вас всегда есть три активных копии:

  • Копия коммита HEAD заморожена и доступна только для Git.
  • Копия индекса слащавая: только для Git, но не совсем замороженная. Изначально он соответствует копии HEAD, но вы можете перезаписать его копией git add.
  • Копия рабочего дерева является нормальной и гибкой, и вы можете делать с ней что угодно.

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

Это оставляет нам проблему, которую нужно решить: что, если в середине работы над чем-то нам нужно довольно срочно исправить какую-то ошибку в какой-то другой ветке? Мы могли бы сделать еще один клон, и это был традиционный ответ. Если мы не находимся в процессе конфликтного слияния, мы могли бы использовать git stash; это был другой ответ. Одно не очень удовлетворительно, а другое бесполезно, если мы находимся в процессе слияния.

Итак, введите git worktree add. Используя git worktree add, вы можете добавить еще одну пару индексного и рабочего дерева в существующий репозиторий. Существует одно очень сильное ограничение (по уважительной причине, связанной с реализацией): каждое добавляемое рабочее дерево должно находиться в своей собственной ветке, иначе используется режим "отдельная HEAD". То есть, если ваше основное рабочее дерево находится на ветке feature/short, ни одно добавленное рабочее дерево не может использовать эту ветвь. Они могут использовать master, hotfix или develop, но не feature/short. (Или они могут использовать отсоединенный HEAD при любой фиксации в любом месте репозитория.)

Когда вы закончите с любым из добавленных вторичных рабочих деревьев, вы можете просто rm -rf его, а затем запустить git worktree prune из одного из других вторичных рабочих деревьев или основного рабочего дерева, чтобы Git искал, а не - найти добавленное рабочее дерево. Это «разблокирует» любую ветвь, которую извлекло добавленное рабочее дерево.

Между тем, команда git subtree представляет собой причудливый сценарий оболочки, который позволяет вам извлечь часть вашего существующего репозитория в новый, который вы будете использовать в другом месте, или взять существующий, который вы используете в другом месте, и попытаться вернуть что-то из него. Так что это передача из одного репозитория в другой — или, по крайней мере, настройка для него в некоторых случаях.

(RomainValeri также упомянул стратегию слияния git-merge-subtree, которая как бы связана со git subtree тем, что она направлена ​​на обработку переименования поддерева в один или два из трех входов для слияния.)

person torek    schedule 11.02.2019
comment
Спасибо за ваш обстоятельный и пропитанный потом ответ. Я очень ценю это. Теперь я знаю, что они разные, но после всех операций и состояний у меня болит голова. Возможно, мне пора сложить меч и поддаться поражению. По подавляющему большинству технических тем я могу с легкостью разобраться, но Git требует разума человека, страдающего синдромом Асперберга, чтобы по-настоящему понять его. Вероятно, это великолепная сумма для любого, кто может концептуально связать Git с более слабыми умами, такими как я. - person ATL_DEV; 12.02.2019

Эти понятия не похожи, и сравнение кажется странным, если не считать похожего звучания.

git worktree (doc) — это правильная команда git (тогда как поддерево — это вклад, спасибо Chris для информации), который в основном помогает вам управлять несколькими рабочими деревьями в одном и том же репо с помощью нескольких дополнительных подкоманд (list, add и т. д. .).

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

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

person RomainValeri    schedule 11.02.2019