2009-03-04 6 views
53

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

Получает ли Git это и как?

(отказ от ответственности: Все, что я знаю о Git на основе Linus лекции - общий мерзавец нуб здесь)

+8

В ответ на: «SVN сделал разветвление намного проще, сделав ветки действительно дешевыми». Вы уверены, что случайно не заменили Git на SVN? Я знаю, что одна из больших возможностей Git - это дешевое разветвление ... Я слышал, что ветвление в SVN - это кошмар, потому что большая часть из них является ручной (создайте новый каталог с разветвленным контентом и т. Д.). – Stunner

ответ

73

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

Но чтобы иметь представление о «как слияния были продуманы», вы can start by turning to Linus himself, и понимаю, что это вопрос не столько о «алгоритм»:

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

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

Иными словами, важная часть - это trivial часть: имя родителей и отслеживание их отношений. Не столкновения.

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


Так Wincent Colaiuta добавляет (курсив мой):

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

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

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

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

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

+1

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

+0

можете ли вы объяснить, что такое дерево? git n00b здесь. – hasen

+0

hansen_j, для получения дополнительной информации о деревьях git читайте http://www.newartisans.com/2008/04/git-from-the-bottom-up.html –

5

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

-10

Git просто затрудняет испортить хранилище всех остальных с плохим слиянием.

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

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

+2

Git также отличается от других. Он рассматривает разницу в содержании, а не файл по редактированию строки. – Saem

16

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

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

Примите за счет следующей диаграммы:

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

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

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

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


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

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

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

Я попытался улучшить диаграмму, форматируя ее как цитату блока ... Надеюсь, я не сломал ее из-за недостаточного понимания, мои извинения в этом случае. – unwind

9

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

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

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

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

+2

Я думаю, вы забываете о слиянии, которое svn имеет с недавнего времени. –

+3

Это правда, у меня не было много опыта с новым материалом слияния. С расстояния он выглядит клочковым: «Когда-то слияние реинтеграции происходит от ветки к стволу, ветка больше не пригодна для дальнейшей работы. Она не способна правильно поглощать новые изменения ствола ...» лучше, чем ничего, конечно. – jdwyah

Смежные вопросы