Что делает объединение в DVCS простым? - PullRequest
48 голосов
/ 10 апреля 2010

Я читаю на Джоэл о программном обеспечении :

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

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

и HgInit :

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

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

Глядя на папку репозитория SVN, у меня складывается впечатление, что Subversion поддерживает каждую ревизию как changeset . И насколько я знаю, Hg использует и changeset , и snapshot , в то время как Git просто использует snapshot для хранения данных.

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

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

  • Меня больше интересует техническая перспектива, но ответы с нетехнической точки зрения приемлемы
  • Исправления:
    1. Концептуальная модель Git основана исключительно на снимках. Снимки могут быть сохранены в виде различий других снимков, просто они предназначены только для оптимизации хранилища. - Rafał Dowgird комментарий
  • С нетехнической точки зрения:
    1. Это просто культурно: DVCS не будет работать вообще, если объединение будет сложным, поэтому разработчики DVCS тратят много времени и усилий на то, чтобы сделать объединение простым. Пользователи CVCS OTOH привыкли к дурацкому слиянию, поэтому у разработчиков нет стимула заставить его работать. (Зачем делать что-то хорошее, когда ваши пользователи платят вам одинаково хорошо за что-то дерьмо?)
      ...
      Напомним: весь смысл DVCS состоит в том, чтобы иметь много децентрализованных репозиториев и постоянно объединять изменения назад и вперед. Без хорошего слияния DVCS просто бесполезен. CVCS, однако, все еще может выжить с дерьмовым слиянием, особенно если поставщик может заставить своих пользователей избегать ветвления. - Йорг Миттаг ответ
  • С технической точки зрения:
    1. запись реального DAG истории действительно помогает! Я думаю, что главное отличие состоит в том, что CVCS не всегда регистрирует слияние как набор изменений с несколькими родителями, теряя некоторую информацию. - tonfa комментарий
    2. из-за отслеживания слияния и более фундаментального факта, что каждой ревизии знает своих родителей . ... Когда каждая ревизия (каждая фиксация), включая коммиты слияния, знают своих родителей (для коммитов слияния, которые означают наличие / запоминание более одного родителя, т.е. отслеживание слияния), вы можете восстановить диаграмму (DAG = прямой ациклический график) ревизии история. Если вы знаете график ревизий, вы можете найти общего предка коммитов, которые вы хотите объединить. И когда ваш DVCS знает, как найти общего предка , вам не нужно указывать его в качестве аргумента, как, например, в CVS.
      .
      Обратите внимание, что там миДолжно быть более одного общего предка двух (или более) коммитов. Git использует так называемую «рекурсивную» стратегию слияния, которая объединяет базы слияния (общий предок), пока у вас не останется один виртуальный / эффективный общий предок (в некотором упрощении) и может выполнить простое трехстороннее слияние. - Якуб Наребски ответ

Проверьте также Как и / или почему слияние в Git лучше, чем в SVN?

Ответы [ 9 ]

32 голосов
/ 10 апреля 2010

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

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

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

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

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

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

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

23 голосов
/ 11 апреля 2010

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

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

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

Использование Git обнаружение переименования было создано, чтобы иметь возможность обрабатывать слияния, связанные с переименованием файлов. (Это поддерживает аргумент Jörg W Mittag о том, что DVCS имеет лучшую поддержку слияния, потому что она должна была иметь это, поскольку слияния встречаются гораздо чаще, чем в CVCS с его слиянием, скрытым в команде update, в update-then- рабочий процесс, cf Понимание системы контроля версий (WIP), Эрик С. Рэймонд).

10 голосов
/ 11 апреля 2010

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

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

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

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

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

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

7 голосов
/ 11 апреля 2010

Ух ты, атака эссе из 5 пунктов!

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

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

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

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

2 голосов
/ 22 апреля 2010

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

1 голос
/ 07 мая 2012

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

1 голос
/ 11 апреля 2010

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

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

Довольно классные вещи.

1 голос
/ 11 апреля 2010

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

Итак:

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

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

Итак, подведем итог:

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

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

0 голосов
/ 11 апреля 2010

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

...