Как Git решает проблему слияния? [закрытый]



SVN сделал ветвление намного проще, сделав ветви действительно дешевыми, но слияния остаются реальной проблемой в SVN - той, которую git предположительно решает.



git достигает этого, и как?



(отказ от ответственности: все, что я знаю о Git, основано на лекции Линуса - total git noob здесь)

654   5  

5 ответов:

Git не предотвратит конфликт в слияниях, но может согласовать историю, даже если они не имеют общего родительского предка.
(через файл графтов (.git/info/grafts), который представляет собой список, по одному на строку, фиксации, за которым следуют его родители, которые вы можете изменить для этой цели "согласования".)
Так что довольно мощный прямо там.

но чтобы действительно взглянуть на "как слияния были продуманы", вы можно начать с обращения к самому Линусу, и понимают этот вопрос не столько про "алгоритм":

Лайнус: я лично, я хочу иметь что-то очень повторяемое и неумное. Что-то я понимаю или говорит мне, что он не может этого сделать.
И совершенно откровенно, слияние однофайловой истории без принимая во внимание историю всех других файлов, я иду "тьфу".

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

другими словами, важной частью является тривиальные часть: именование родителей и отслеживание их отношений. Только не столкновения.

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


поэтому Wincent Colaiuta добавляет (акцент мой):

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

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

абсолютно все может (и должно) быть выведено.

Git ломает форму, потому что он думает о содержании, а не о файлах.
Он не отслеживает переименования, он отслеживает контент. И это происходит на уровне целого дерева.
Это радикальный отход от большинства систем контроля версий.
Он не пытается хранить истории для каждого файла; вместо этого он хранит историю в дереве уровень.
При выполнении diff вы сравниваете два дерева, а не два файла.

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

в настоящее время общепризнано, что 3-сторонний алгоритм слияния (возможно, с такими улучшениями, как обнаружение переименования и работа с более сложной историей), который учитывает версию на текущей ветви ("наша"), версию на объединенной ветви ("их") и версию общего предка Объединенных ветвей ("предок"), является (с практической точки зрения) лучшим способом разрешения слияний. В большинстве случаев, и для большей части уровня дерева содержимого слияния (какая версия файла взять) является достаточно; редко возникает необходимость в решении конфликтов содержимого, и тогда алгоритм diff3 достаточно хорош.

чтобы использовать 3-полосное слияние, вам нужно знать общий предок Объединенных ветвей (co называется merge base). Для этого вам нужно знать полное история между этими ветвями. То, что Subversion до (текущей) версии 1.5 отсутствовало (без сторонних инструментов, таких как SVK или svnmerge) было отслеживание слияний, т. е. запоминание для слияния фиксации какие родители (какие коммиты) использовались в слиянии. Без этой информации невозможно правильно вычислить общего предка при наличии повторных слияний.

примите во внимание следующую диаграмму:

---.---a---.---b---d---.---1
        \        /
         \-.---c/------.---2

(который, вероятно, будет искалечен... было бы неплохо иметь возможность рисовать диаграммы ASCII-art здесь).
Когда мы объединяли коммиты ' b 'и' c '(создавая коммит 'd'), общим предком был точка ветвления, фиксация 'a'. Но когда мы хотим объединить коммиты '1' и '2', теперь общим предком является commit 'c'. Без хранения информации о слиянии нам пришлось бы ошибочно заключить, что это commit 'a'.

Subversion (до версии 1.5) и более ранние CVS затрудняли слияние, потому что вам приходилось самостоятельно вычислять общего предка и давать информацию о предке вручную при выполнении слияния.

Git хранит информацию обо всех родителях фиксации (более одного родитель в случае фиксации слиянием) в объекте фиксации. Таким образом, Вы можете сказать, что Git хранит DAG (прямой ациклический граф) ревизий, хранения и запоминания отношений между коммитами.


(Я не уверен, как Subversion имеет дело с проблемами, упомянутыми ниже)

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

  • файл переименовывается во время слияния управляются с использованием эвристической оценки сходства (учитывается как сходство содержимого файла, так и сходство пути)переименовать обнаружения. Git определяет, какие файлы соответствуют друг другу в Объединенных ветвях (и предок(и)). На практике это работает довольно хорошо для реальных случаев.
  • крест-накрест сливается см. определение at revctrl.org Вики, (и наличие несколько баз слияния) осуществляется с помощью рекурсивная стратегия слияния, который генерирует одного виртуального общего предка.

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

svn merge -r 23:30 file:///tmp/repos/trunk/vendors

теперь это не убийца, но если вы забудете, является ли это 23-30 включительно или 23-30 эксклюзивно, или вы уже слили некоторые из этих коммитов, вы обливаетесь, и вам нужно найти ответы, чтобы избежать повторения или пропуска коммитов. Боже, помоги! вы, если вы разветвляете ветку.

с git это просто слияние git, и все это происходит легко, даже если вы выбрали пару коммитов или сделали любое количество фантастических вещей git-land.

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

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

единственное реальное преимущество заключается в том, что Git намного быстрее при слиянии, потому что все делается локально и написано на C.

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

Comments

    Ничего не найдено.