Что делает слияние в DVCS легким?

Я читал в Joel на программном обеспечении:

С распределенным управлением версиями распределенная часть является на самом деле не самой интересной частью.

Интересная часть - то, что эти системы думают с точки зрения изменений, не с точки зрения версий.

и в HgInit:

Когда мы должны объединиться, Подверсия пытается посмотреть на оба изменения — мой измененный код и Ваш измененный код — и она пытается предположить, как разбить их вместе в одной большой безобразной путанице. Это обычно перестало работать, производя страницы и страницы “конфликтов слияния”, которые не являются действительно конфликтами, просто места, где Подверсии не удалось выяснить то, что мы сделали.

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

Путем рассмотрения папки репозитория SVN у меня есть впечатление, что Подверсия поддерживает каждого изменения как changeset. И от того, что я знаю, Hg использует и changeset и снимок, в то время как Мерзавец просто использует снимок, чтобы хранить данные.

Если мое предположение корректно, то должны быть другие пути, которые делают слияние в DVCS легким. Что это?

* обновление:

  • Я больше интересуюсь технической перспективой, но ответы с нетехнической точки зрения приемлемы
  • Исправления:
    1. Концептуальная модель мерзавца просто основана на снимках. Снимки могут быть сохранены как diffs других снимков, это просто, что diffs просто для оптимизации системы хранения. – Комментарий Rafał Dowgird
  • С нетехнической точки зрения:
    1. Это просто культурно: DVCS не работал бы вообще, если слияние было трудно, таким образом, разработчики DVCS инвестируют много времени и усилия в создание легкого слияния. Пользовательские OTOH CVCS привыкли к дрянному слиянию, таким образом, нет никакого стимула для разработчиков заставить его работать. (Почему делают что-то хорошим, когда Ваши пользователи платят, Вы одинаково хорошо для чего-то гадите?)
      ...
      Резюмировать: смысл DVCS должен иметь много децентрализованных репозиториев и постоянно объединять изменения назад и вперед. Без хорошего слияния DVCS просто бесполезен. CVCS однако, может все еще выжить с дрянным слиянием, особенно если поставщик может тренировать его пользователей, чтобы не переходить. – Ответ W Mittag Jörg
  • С технической точки зрения:
    1. запись реального DAG истории действительно помогает! Я думаю, что основное различие - то, что CVCS не всегда записывал слияние как changeset с несколькими родителями, теряя некоторую информацию. – комментарий тонфы
    2. из-за отслеживания слияния и более фундаментального того, что каждый изменения знает его родителей.... Когда каждый пересмотр (каждая фиксация), включая фиксации слияния, знает своих родителей (для фиксаций слияния, который означает иметь/помнить больше чем одного родителя, т.е. отслеживание слияния), можно восстановить схему (DAG = Прямой Граф без петель) истории пересмотра. Если Вы знаете график изменений, можно найти общего предка фиксаций, которые Вы хотите объединить. И когда Ваша DVCS знает себя, как найти общего предка, Вы не должны обеспечивать ее как аргумент, что касается примера в CVS.
      .
      Обратите внимание, что мог бы быть больше чем один общий предок два (или больше) фиксации. Мерзавец использует так называемую "рекурсивную" стратегию слияния, которая объединяет основания слияния (общий предок), пока Вас не оставляют с одним виртуальным / эффективный общий предок (в некотором упрощении), и может простого слияния с 3 путями. – Ответ Jakub Narębski

Проверьте также, Как и/или почему объединяется в Мерзавце лучше, чем в SVN?

48
задан Community 23 May 2017 в 12:00
поделиться

8 ответов

В Git и других DVCS слияние легко не из-за мистической серии наборов изменений (если только вы не используете Darcs с его теорией патчей или какую-нибудь DVCS, вдохновленную Darcs; их, правда, меньшинство), о которой рассказывает Джоэл, а из-за отслеживания слияний и более фундаментального факта, что каждая ревизия знает своих родителей. Для этого вам нужны (я думаю) коммиты по всему дереву / всему хранилищу... что, к сожалению, ограничивает возможность делать частичные проверки и делать коммит только для подмножества файлов.

Когда каждая ревизия (каждый коммит), включая коммиты слияния, знает своих родителей (для коммитов слияния это означает иметь/помнить более одного родителя, т.е. merge tracking), вы можете построить диаграмму (DAG = Direct Acyclic Graph) истории ревизий. Если вы знаете граф ревизий, вы можете найти общего предка коммитов, которые вы хотите объединить. А когда ваш DVCS сам знает, как найти общего предка, вам не нужно указывать его в качестве аргумента, как, например, в CVS.

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

Git использует обнаружение переименований было создано для того, чтобы иметь возможность работать со слияниями, включающими переименования файлов. (Это поддерживает аргумент Jörg W Mittag, что DVCS имеют лучшую поддержку слияния, потому что они должны были иметь её, так как слияния происходят гораздо чаще, чем в CVCS с её слиянием, скрытым в команде 'update', в рабочем процессе update-then-commit, например Understanding Version Control (WIP) Eric S. Raymond).

23
ответ дан 26 November 2019 в 18:58
поделиться

В DVCS нет ничего особенного, что облегчало бы слияние. Это просто культурно: DVCS вообще не работал бы , если бы слияние было трудным, поэтому разработчики DVCS вкладывают много времени и усилий, чтобы упростить слияние. Пользователи CVCS OTOH привыкли к дерьмовому слиянию, поэтому у разработчиков нет стимула заставить его работать. (Зачем делать что-то хорошее, если ваши пользователи одинаково хорошо платят вам за что-то дерьмо?)

Линус Торвальдс сказал в одном из своих выступлений на Git, что, когда он использовал CVS в Transmeta, они выделяли целую неделю во время цикла разработки для слияния. И все просто восприняли это как нормальное положение вещей. В настоящее время во время окна слияния Линус выполняет сотни слияний всего за несколько часов.

CVCS могли бы иметь такие же хорошие возможности слияния, как и DVCS, если бы пользователи CVCS просто обратились к своим поставщикам и сказали, что эта чушь неприемлема. Но они пойманы парадоксом Блаба: они просто не знают , что это неприемлемо, потому что они никогда не видели работающей системы слияния. Они не знают, что есть что-то лучшее.

И когда они действительно пробуют DVCS, они волшебным образом приписывают все достоинства части "D".

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

Напомним: весь смысл DVCS состоит в том, чтобы иметь много децентрализованных репозиториев и постоянно объединять изменения туда и обратно. Без хорошего слияния DVCS просто бесполезен. Однако CVCS все еще может выжить при неудачном слиянии, особенно если поставщик может заставить своих пользователей избегать ветвления.

Так что, как и все остальное в программной инженерии, это вопрос усилий.

32
ответ дан 26 November 2019 в 18:58
поделиться

Возможно, пользователи DVCS просто никогда не делают вещи, которые усложняют слияние, например рефакторинги, которые изменяют и переименовывают / копируют большинство файлов в проекте, или перепроектируют из stratch API, которые используются в сотнях файлов.

-10
ответ дан 26 November 2019 в 18:58
поделиться

Вау, атака эссе из 5 параграфов!

Короче говоря, ничто не облегчает задачу. Это трудно, и мой опыт показывает, что ошибки случаются. Но:

  • DVCS заставляет вас иметь дело с объединением, а это значит, что вам придется потратить несколько минут на ознакомление с инструментами, которые существуют, чтобы помочь вам. Уже одно это помогает.

  • DVCS поощряет вас к частому объединению, что тоже помогает.

Фрагмент hginit, который вы процитировали, утверждающий, что Subversion не может делать трехстороннее слияние и что Mercurial делает слияние, просматривая все наборы изменений в обеих ветках, просто неверен по обоим пунктам.

7
ответ дан 26 November 2019 в 18:58
поделиться

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

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

Довольно крутая штука.

1
ответ дан 26 November 2019 в 18:58
поделиться

Частично причина, конечно, в техническом аргументе, что DVCSes хранит больше информации, чем SVN (DAG, копирует ), а также имеет более простую внутреннюю модель, поэтому она может выполнять более точные слияния, как упоминалось в других ответах.

Однако, вероятно, еще более важным отличием является то, что, поскольку у вас есть локальный репозиторий, вы можете делать частые небольшие коммиты, а также часто извлекать и объединять входящие изменения. Это вызвано больше «человеческим фактором», различиями в том, как человек работает с централизованной VCS по сравнению с DVCS.

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

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

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

И , если окажется конфликт, вы можете отложить слияние и сделать это на досуге. Это, в частности, делает слияние менее утомительным.

10
ответ дан 26 November 2019 в 18:58
поделиться

Я думаю, что DAG наборов изменений, как упоминалось другими, имеет большое значение. DVCS: es требует разбиения истории (и слияний) на фундаментальном уровне, тогда как я полагаю, что CVCS: es (которые старше) были созданы с первого дня для отслеживания ревизий и файлов в первую очередь, а поддержка слияния добавляется в качестве запоздалой мысли.

Итак:

  • Слияние легко выполнять и отслеживать, когда теги / ветви отслеживаются отдельно от дерева каталогов источников, поэтому все репо можно объединить за один раз.
  • Поскольку DVCS: es имеют локальные репозитории, их легко создать, поэтому оказывается, что легко хранить разные модули в разных репозиториях вместо того, чтобы отслеживать их все внутри большого репо. (поэтому слияния в масштабе всего репо не вызывают таких же сбоев, как в svn / cvs, где одно репо часто содержит много несвязанных модулей, которым требуется отдельная история слияния.)
  • CVS / SVN позволяет работать с разными файлами. каталог из разных ревизий, в то время как DVCS: es обычно имеет одну ревизию для всего WC, всегда (т.е. даже если файл будет возвращен к более ранней версии, он будет отображаться как измененный в статусе, поскольку он отличается от файла в проверенная ревизия. SVN / CVS не всегда показывает это.)

Смешивание этих концепций (как это делает Subversion), я полагаю, является большой ошибкой. Например, в исходном дереве есть ветки / теги, поэтому вам нужно отслеживать, какие версии файлов были объединены с другими файлами. Это явно более сложно, чем просто отслеживать, какие ревизии были объединены.

Итак, резюмируя:

  • DVCS: es нуждаются в простом слиянии, имеют свой набор функций, основанный на этом.Проектное решение было принято таким образом, чтобы эти слияния можно было легко выполнять и отслеживать (через DAG), а другие функции (ветки / теги / подмодули) реализованы для этого, а не наоборот.
  • В CVCS: es с самого начала были некоторые функции (например, модули), которые упрощали некоторые вещи, но делали слияния на уровне репозитория очень сложными для реализации.

По крайней мере, это то, что я чувствую из моего опыта работы с cvs, svn, git и hg. (Вероятно, есть и другие CVCS: es, которые тоже правильно поняли.)

1
ответ дан 26 November 2019 в 18:58
поделиться

Один момент заключается в том, что слияние svn слегка нарушено; см. http://blogs.open.collab.net/svn/2008/07/subversion-merg.html Я подозреваю, что это связано с svn-записью mergeinfo даже при слиянии с отбором вишен. Добавьте несколько простых ошибок в обработке пограничных случаев, и svn в качестве текущего дочернего элемента CVCS заставляет их выглядеть плохо, в отличие от всех DVCS, которые только что сделали это правильно.

2
ответ дан 26 November 2019 в 18:58
поделиться