Я часто читаю, что Hg (и Git и ...) лучше объединяются, чем SVN, но я никогда не видел практических примеров того, как Hg / Git может слить что-то, где SVN выходит из строя (или где SVN требует ручного вмешательства). Не могли бы вы опубликовать несколько пошаговых списков операций ветвления / изменения / фиксации /...-, которые показывают, где SVN потерпит неудачу, в то время как Hg / Git счастливо движется? Практические, не исключительные случаи, пожалуйста ...
Немного предыстории: у нас есть несколько десятков разработчиков, работающих над проектами, использующими SVN, с каждым проектом (или группой похожих проектов) в своем собственном репозитории. Мы знаем, как применять ветки релизов и функций, чтобы мы не сталкивались с проблемами очень часто (то есть, мы были там, но мы научились преодолевать проблемы Джоэла «одного программиста, причиняющего травму всей команде»). или "требуется шесть разработчиков на две недели для реинтеграции филиала"). У нас есть ветки релизов, которые очень стабильны и используются только для исправления ошибок. У нас есть транки, которые должны быть достаточно стабильными, чтобы иметь возможность создавать релиз в течение одной недели. И у нас есть тематические ветви, над которыми могут работать отдельные разработчики или группы разработчиков. Да, они удаляются после реинтеграции, поэтому они не загромождают репозиторий. ;)
Поэтому я все еще пытаюсь найти преимущества Hg / Git перед SVN. Я бы хотел получить практический опыт, но пока нет более крупных проектов, которые мы могли бы перевести на Hg / Git, поэтому я застрял в игре с небольшими искусственными проектами, которые содержат только несколько готовых файлов. И я ищу несколько случаев, когда вы можете почувствовать впечатляющую силу Hg / Git, поскольку до сих пор я часто читал о них, но сам не смог их найти.
Ответы:
Сам я не использую Subversion, но из примечаний к выпуску Subversion 1.5: отслеживание слияний (основополагающее) похоже, что есть следующие отличия от того, как работает отслеживание слияний в системах контроля версий с полной DAG , таких как Git или Mercurial.
Слияние транка с веткой отличается от слияния ветки с транком: по некоторым причинам слияние транка с веткой требует
--reintegrate
опцииsvn merge
.В распределенных системах контроля версий, таких как Git или Mercurial, нет никакой технической разницы между стволом и ветвью: все ветви созданы равными ( хотя может быть социальная разница). Слияние в любом направлении выполняется одинаково.
Вам необходимо предоставить опцию new
-g
(--use-merge-history
)svn log
иsvn blame
учесть отслеживание слияний.В Git и Mercurial отслеживание слияний автоматически учитывается при отображении истории (журнала) и вины. В Git вы можете запросить подписку на первого родителя только с помощью
--first-parent
(я думаю, что подобная опция существует и для Mercurial), чтобы «отбросить» информацию об отслеживании слияний вgit log
.Из того, что я понимаю,
svn:mergeinfo
свойство хранит информацию о конфликтах по каждому пути (Subversion основана на наборах изменений), тогда как в Git и Mercurial это просто коммит объектов, которые могут иметь более одного родителя.Подраздел «Известные проблемы» для отслеживания слияния в Subversion предполагает, что повторное / циклическое / отражающее слияние может работать неправильно. Это означает, что в следующих историях второе слияние может не сработать («A» может быть стволом или ответвлением, а «B» может быть ответвлением или стволом соответственно):
В случае, если вышеприведенный ASCII-art нарушается: ветвь «B» создается (разветвляется) из ветки «A» при ревизии «x», затем более поздняя ветвь «A» объединяется при ревизии «y» в ветку «B» как слияние 'M1', и, наконец, ветвь 'B' объединяется с ветвью 'A' как слияние 'M2'.
В случае, если вышеприведенный ASCII-art нарушается: ветвь «B» создается (разветвляется) из ветки «A» при ревизии «x», она объединяется с ветвью «A» в «y» как «M1», а затем снова объединены в ветвь «A» как «M2».
Subversion может не поддерживать расширенный случай слияния .
Git прекрасно справляется с этой ситуацией на практике, используя «рекурсивную» стратегию слияния. Я не уверен насчет Mercurial.
В «Известных проблемах» есть предупреждение о том, что отслеживание слияний может не работать с переименованием файлов, например, когда одна сторона переименовывает файл (и, возможно, изменяет его), а вторая сторона изменяет файл без переименования (под старым именем).
И Git, и Mercurial на практике справляются с таким случаем: Git использует обнаружение переименования , Mercurial использует отслеживание переименования .
НТН
источник
<pre>...</pre>
блока не имеет отступов, как должно быть ...--reintegrate
устарела.Я тоже искал случай, когда, скажем, Subversion не может слить ветку и Mercurial (а Git, Bazaar, ...) делает правильные вещи.
Книга SVN описывает, как переименованные файлы объединяются неправильно . Это относится к Subversion 1.5 , 1.6 , 1.7 и 1.8 ! Я попытался воссоздать ситуацию ниже:
Согласно книге, слияние должно завершиться чисто, но с неверными данными в переименованном файле, так как обновление на
trunk
забыто. Вместо этого я получаю конфликт дерева (это с Subversion 1.6.17, новейшей версией Debian на момент написания):Никакого конфликта не должно быть - обновление должно быть объединено с новым именем файла. В то время как Subversion терпит неудачу, Mercurial обрабатывает это правильно:
Перед слиянием репозиторий выглядит так (с
hg glog
):Выход слияния:
Другими словами: Mercurial взял изменение из ревизии 1 и объединил его с новым именем файла из ревизии 2 (
hello.en.txt
). Разумеется, обработка этого случая необходима для поддержки рефакторинга, а рефакторинг - это именно то, что вы захотите сделать в ветке.источник
Не говоря об обычных преимуществах (коммиты в автономном режиме, процесс публикации , ...), вот пример «слияния», который мне нравится:
Основной сценарий, который я продолжаю видеть, - это ветка, в которой ... фактически разрабатываются две несвязанные задачи
(она началась с одной функции, но привела к разработке этой другой функции.
Или она началась с патча, но это привело к разработка другой функции).
Как вам слить только одну из двух функций на основной ветке?
Или как вы изолируете две функции в своих собственных ветках?
Вы можете попытаться сгенерировать какие-то патчи, проблема в том, что вы больше не уверены в функциональных зависимостях. которые могли бы существовать между:
Git (и Mercurial, я полагаю) предлагает опцию rebase --onto для перебазирования (сброса корня ветви) части ветви:
Из поста Джефроми
Вы можете распутать ситуацию, когда у вас есть патчи для v2, а также новая функция wss:
, что позволяет вам:
Еще одна особенность, которая мне нравится (которая влияет на слияния), - это возможность фиксировать коммиты (в ветке, еще не перенесенной в другое хранилище), чтобы представить:
Это обеспечивает слияния, которые намного проще, с меньшим количеством конфликтов.
источник
Мы недавно мигрировали из SVN в GIT и столкнулись с такой же неопределенностью. Было много неофициальных доказательств того, что GIT был лучше, но трудно было найти какие-либо примеры.
Я могу сказать вам, однако, что GIT намного лучше при слиянии, чем SVN. Это, очевидно, анекдотично, но есть таблица для подражания.
Вот некоторые из вещей, которые мы нашли:
Когда мы оценивали GIT, мы проводили следующие тесты. Они показывают GIT как победителя, когда дело доходит до слияния, но не настолько. На практике разница намного больше, но я думаю, нам не удалось воспроизвести ситуации, которые SVN плохо обрабатывает.
источник
Другие охватили более теоретические аспекты этого. Может быть, я могу дать более практическую перспективу.
В настоящее время я работаю в компании, которая использует SVN в модели разработки "ветки". То есть:
В общем, работает. SVN можно использовать для такого потока, но он не идеален. Есть некоторые аспекты SVN, которые мешают и формируют поведение человека. Это дает некоторые негативные аспекты.
^/trunk
. Это засоряет записи информации о слиянии по всему дереву и в конечном итоге нарушает отслеживание слияния. Ложные конфликты начинают появляться, и царит путаница.svn merge
делает то, что вы хотите. Для--reintegrate
объединения ваших изменений требуется (как нам сказали) команда слияния. Я никогда по-настоящему не понимал этот переключатель, но это означает, что ветвь не может быть снова объединена с транком. Это означает, что это мертвая ветка, и вы должны создать новую, чтобы продолжить работу. (Смотрите примечание)Обычно случается, что инженер создает филиал в первый день. Он начинает свою работу и забывает об этом. Через некоторое время приходит босс и спрашивает, может ли он выпустить свою работу в багажник. Инженер боялся этого дня, потому что реинтеграция означает:
... и поскольку инженер делает это как можно меньше, он не может вспомнить "магическое заклинание", чтобы сделать каждый шаг. Происходят неправильные переходы и URL-адреса, и они внезапно оказываются в беспорядке и получают «эксперта».
В конце концов все успокаивается, и люди учатся исправлять недостатки, но каждый новый стартер сталкивается с одними и теми же проблемами. Возможная реальность (в отличие от того, что я изложил в начале):
...но...
К счастью, команда достаточно мала, чтобы справиться, но она не будет масштабироваться. Дело в том, что ни одна из этих проблем не является проблемой с CVCS, но более того, поскольку слияния не так важны, как в DVCS, они не так удобны. Это «трение слияния» вызывает поведение, которое означает, что модель «Feature Branch» начинает разрушаться. Хорошие слияния должны быть свойством всех VCS, а не только DVCS.
В соответствии с этим теперь есть
--record-only
переключатель, который можно использовать для решения--reintegrate
проблемы, и, по- видимому, v1.8 выбирает, когда выполнять реинтеграцию автоматически, и это не приводит к тому, что ветвь впоследствии становится мертвой.источник
До Subversion 1.5 (если я не ошибаюсь) у Subversion был существенный недостаток в том, что он не запоминал историю слияний.
Давайте посмотрим на случай, изложенный VonC:
Обратите внимание на ревизии A и B. Скажем, вы слили изменения из ревизии A в ветке "wss" в ветку "v2-only" в ревизии B (по любой причине), но продолжили использовать обе ветки. Если вы попытаетесь снова объединить две ветви, используя mercurial, он объединит изменения только после ревизий A и B. В Subversion вам придется объединить все, как если бы вы не делали слияние раньше.
Это пример из моего собственного опыта, где слияние из B в A заняло несколько часов из-за объема кода: это было бы настоящей болью для повторения , что было бы в случае с Subversion pre-1.5.
Еще одно, вероятно, более существенное отличие в поведении слияний от Hginit: перевоспитание Subversion :
Короче говоря, метод анализа различий в Mercurial (был?) Превосходит метод Subversion.
источник