Что такого сложного в слияниях SVN?

28

Возможный дубликат:
я фанат Subversion, почему я должен рассматривать или не рассматривать Mercurial или Git или любой другой DVCS?

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

И случай использования, который неизменно поднимается, - это повторное объединение филиала, что снова напоминает мне о тех рекламных объявлениях о продуктах-соломочках; если вы знаете, что делаете, вы не должны (и никогда не должны) заново объединять ветку. (Конечно, это трудно сделать, когда ты делаешь что-то принципиально неправильное и глупое!)

Итак, не говоря уже о нелепом сценарии использования, что в объединении SVN по своей сути сложнее, чем в системе DVCS?

Мейсон Уилер
источник
6
Мне еще предстоит работать в среде, где они объединяют ветки длиной в месяцы и используют распределенный контроль версий. Единственные места, где я работал, для таких долгоживущих веток, использовали TFS / Subversion. Я ожидаю, что такие долгоживущие ветки будет сложно объединить с DVCS.
Одед
13
@MasonWheeler Я озадачен. Тогда для чего вы используете VCS? Я видел и читал, что одна из многих рекомендуемых практик - иметь функциональные ветви. В этом случае слияние обратно в транк обязательно. Или я что-то не так понял? (да, метафора дерева ломается, но начинать с ИМО было не так уж и полезно)
Андрес Ф.
9
@MasonWheeler: Я думаю, вы слишком буквально понимаете аналогию с деревьями.
whatsisname
8
@MasonWheeler, сколько разных сред разработки у вас есть, если вы никогда не слышали о слиянии с транком? В некоторых магазинах есть стабильные стволы и экспериментальные отделения, и в этом случае вишня, собирающая удачные продукты обратно в конюшню, является регулярным событием.
Брюс

Ответы:

25

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

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

Карл Билефельдт
источник
47

если вы знаете, что делаете, вы не должны (и никогда не должны) заново объединять ветку. (Конечно, это трудно сделать, когда ты делаешь что-то принципиально неправильное и глупое!)

И в этом источник вашей путаницы и всей проблемы в целом.

Вы говорите, что объединение ветвей "в корне неправильно и глупо". Ну, в этом-то и проблема: вы думаете о ветвях как о вещах, которые не следует объединять Зачем? Потому что вы пользователь SVN, который знает, что объединение ветвей сложно . Поэтому вы никогда не делаете этого, и вы поощряете других не делать этого. Вы были обучены избегать слияния; Вы разработали методы, которые используете, чтобы избежать слияния.

Я пользователь Mercurial. Даже на моих собственных проектах, где я единственный разработчик, я сливаю ветви все время . У меня есть ветка релиза, в которую я положил исправление. Ну, я сливаю это обратно в основную линию, чтобы исправить это.

Если бы я использовал SVN, я бы использовал совершенно другую структуру кодовой базы. Зачем? Потому что SVN делает слияния трудными, и поэтому вы разрабатываете идиомы и методы, чтобы избежать сложных слияний.

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

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

Правильный инструмент для правильной работы.

Дело в том, что рабочий процесс, ориентированный на слияние, намного приятнее и проще в использовании, чем рабочий процесс в стиле SVN, где вы не объединяете вещи. Проще увидеть, когда что-то из ветки релиза было перенесено в ветку dev. Проще увидеть различное взаимодействие между ветвями. Легко создавать тестовые ветки для вещей, а затем обрезать их, если тест не работает. И так далее.

На самом деле, Джоэл объясняет это намного лучше, чем я . Вы должны хорошо прочитать это.

Николь Болас
источник
15
@ Мейсон: Как это не обучение? Вы были обучены использовать SVN в стиле SVN. И стиль SVN - не использовать слияние. Таким образом, вы были обучены не использовать или даже рассмотреть возможность объединения вещей. Вот почему это никогда не приходило вам в голову; потому что вы использовали систему, которая усложняет.
Николь Болас
5
Существует большая разница между «не обучен» и «не обучен».
Мейсон Уилер
8
@MasonWheeler: Нет, нет. Если вас не научили правильно делать что-то, то вы неявно обучены не делать этого. Это не входит в ваш репертуар идиом, которые вы можете использовать для решения проблемы. Поэтому вы не можете использовать его для решения проблем. Эффект ничем не отличается от того, что вам говорят не сливаться, потому что даже если вы захотите, вы не знаете как. То, как вы бесцеремонно отбрасываете хороший аргумент, как «та же самая старая усталость», тому подтверждение. Вы не думаете о слиянии как о инструменте; вы думаете об этом как об исключении или о чем-то необычном. Что-то, чтобы подвергнуть сомнению, а не использовать.
Николь Болас
9
@MasonWheeler: Кто ты такой, чтобы решать, « они делают это неправильно »? Вы не используете DVCS, поэтому у вас нет опыта работы с DVCS. Вы понятия не имеете, полезно ли это программистам или нет, поскольку у вас нет опыта работы с ним. Так какой авторитет у вас есть, чтобы сказать, что это «неправильно» только потому, что SVN не позволяет этого? Это все равно что сказать, что классы, виртуальные функции и шаблоны неправильны, потому что в C их нет.
Никол Болас
3
@MasonWheeler: как это? : P . Ветвление и слияние SVN делает то же самое - метафора уже сломана. Я действительно не вижу, как что-то подобное так сложно понять, особенно если оно включает в себя некоторые разумные комментарии коммита ..
naught101
21

В объединении SVN нет ничего сложного ... больше ... если вы следуете правильной философии

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

Из моего текущего опыта использования SVN 1.6 до 1.8 в унаследованном проекте, который я унаследовал недавно, SVN прошел долгий путь к тому, чтобы сделать слияние намного проще. Тем не менее, он не является надежным, и я думаю, что он не так легко переносит пользователей, которые отклоняются от предполагаемого использования.

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

В конечном счете, тем не менее, я понял, что каждый раз, когда у меня возникает одна (или какая-то другая проблема), это происходит потому, что я не все сделал правильно (так называемый «путь SVN» - возможно, правильный способ контроля версий). Я полагаю, что именно в этом и заключается трудность: вы не можете делать что-то, что хотите, неорганизованным образом и ожидать, что SVN будет работать идеально, особенно с объединениями. Слияния требуют строгой дисциплины от пользователей, прежде чем они покажут свою истинную силу.

Вот что я заметил, это строгие рекомендации, если не требования, для чистого использования слияний:

  • Используйте последнюю версию SVN (1.6 и выше, на мой взгляд). Все больше автоматизации и проверок делается для вас.
  • Используйте стандартную структуру «ствол, ветви, теги» и применяйте ее философию (не фиксируйте теги). SVN не будет ничего проверять для вас. Если вы используете тег в качестве ветви (это состояние, в котором я обнаружил хранилище проекта), он все еще может работать, но вы должны быть последовательными.
  • Знайте, что ветви и когда их создавать. То же самое с тегами.
  • Держите боковые ветви в актуальном состоянии с их исходной ветвью (обычно это транк, но технически вы можете разветвляться из любой ветки) Это обязательно, если вы хотите, чтобы SVN выполнял автоматическое слияние. SVN 1.8 фактически предотвращает автоматическое объединение, если что-то не обновлено, а также если у вас есть ожидающие изменения в вашей рабочей копии (это поведение, похоже, снова исчезло в 1.8.5).
  • Делайте "правильные" коммиты. Они должны содержать только модификации очень специфической концепции. Насколько это возможно, они должны содержать небольшое количество изменений. Вы не хотите, чтобы один коммит содержал модификации, например, о двух независимых ошибках. Если вы уже исправили оба, и они находятся в одном и том же файле, вы должны сохранить изменения одной ошибки, чтобы вы могли сначала зафиксировать только изменения другой, а затем зафиксировать второй набор изменений. Обратите внимание, что TortoiseSVN позволяет это легко с помощью «Восстановить после фиксации».
    • Это позволяет отменить конкретный независимый набор изменений и дает возможность только объединить такой набор в другую ветвь. Да, SVN позволяет объединять выбранные версии.
  • Если вы когда-либо используете дочерние ветви (ветвление от магистрали, а затем ветвление от этой новой ветки), соблюдайте иерархию. Если вы обновите подчиненную ветку стволом или наоборот, вас ждет некоторая боль. Слияния должны быть расположены вниз или вверх по иерархии.
    • После нескольких месяцев экспериментов я могу подтвердить, что это может быть самой важной частью. Попытка создания двух подветвлений из одной и той же транка, а затем слияние битов между подветвлениями или иногда между под-ветвями с любой стороны. Это может отключить SVN (или пользователя). Это может работать нормально, если вы объединяете определенные ревизии. Авто слияние может иметь проблемы с этим.
    • У меня были проблемы, особенно при синхронизации под-ветви A с транком, а затем при попытке объединить что-то из под-ветви A в под-ветку B. Кажется, что SVN считает, что ревизия «синхронизация из транка» должна быть законно объединена с под-веткой B и это приводит к массе конфликтов.
  • Насколько это возможно, слить из корня ветки. В противном случае, SVN будет держать только след в слияниях сделано для подпапки и когда вы делаете попытку к автоустановкам от корня, вы можете получить предупреждения об отсутствии неслитых изменений. Это можно исправить, просто объединив их из корня, но лучше всего избежать путаницы.
  • Будьте осторожны, какую ветку вы делаете. Если вы используете Switch, чтобы ваша рабочая копия со временем указывала на различные ветви, убедитесь, что вы делаете это.
    • Это особенно плохо, если вы действительно не хотели изменений в этой ветке. Мне все еще неясно, но в зависимости от того, как вы избавитесь от этого / перенесете его в нужную ветвь (возврат, слияние), вы можете получить что-то грязное. Это исправимо, но вам придется либо объединить редакцию за редакцией, чтобы избежать или немедленно разрешить потенциальные конфликты, либо вам придется исправить, возможно, более сложный конфликт после автоматического объединения.
  • Не держите ветки нетронутыми слишком долго. На самом деле, дело не в времени, а в том, сколько ревизий было внесено в ветку и транк и насколько они изменились. Слияния между двумя ветвями, трехсторонние слияния всегда сравниваются с последними общими ревизиями между ветвями Чем больше промежуточных изменений, тем больше изменений не произойдет при автоматическом объединении. Это, конечно, намного хуже, если вы тем временем изменили структуру своего кода (перемещенные или переименованные файлы).

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

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

В общем, легко ли объединить SVN? Я думаю, нет. Конечно, не беззаботно. Это плохо ? Я так не думаю. Он плюет вам в лицо только тогда, когда вы используете его неправильно и не думаете о том, что вы делаете.

Основываясь на этом, я понимаю, почему люди могут предпочесть Mercurial (например), поскольку он немного более снисходительно относится к этим вещам из моего опыта и автоматизировал все с самого начала (по крайней мере, в ранних версиях, с которых я начинал). SVN, тем не менее, догнал немного, так что больше не стоит так сильно ругаться.

leokhorn
источник
Древовидные конфликты - да, SVN испытывает трудности с этим, хотя TBH делает то же самое с любым другим SCM. У Git есть некоторая эвристика, чтобы попытаться выяснить, совпадают ли файлы, которые были переименованы или перемещены, но он (не может!) Не всегда делает это правильно. Я думаю, что SVN должна приложить некоторые усилия, чтобы облегчить понимание этих конфликтов.
gbjbaanb
@gbjbaanb: он предлагает "Repair Move", как Mercurial, хотя и не предлагает эвристики. Вы должны сказать, какие удаленные и добавленные файлы, на самом деле, одинаковы. Определенно возможности для улучшения.
leokhorn
Все это звучит замечательно, когда вы единственный человек, работающий над проектом ... Но если у вас есть команда хорошего размера, и все они используют ее, «путь SVN» (с которым, кажется, никто не согласен, что именно), сливается все еще пита. Дело в том, что SVN не очень хорошо поддерживает рабочий процесс ветвления. «Путь SVN» состоит в том, чтобы даже не создавать ветки и использовать водопад SDLC. Несмотря на это, в прошлом у меня были проблемы с Git-слияниями в крупных проектах, над которыми работали несколько человек. Но они, казалось, все еще были намного менее болезненными.
ryoung
По моему опыту, если вы работаете с людьми, которым не важно, как работает система контроля версий, SVN намного проще в повседневной работе. Я работал только в нескольких командах DVCS, но неизменно значительное количество команды не имеет хорошего поведения контроля версий, и это загрязняет репозиторий для всех. В Subversion неподготовленные, как правило, держатся подальше от филиалов, поэтому они заставляют «экспертов» сделать это за них, и ими управляют соответствующим образом. Конечно, этот опыт мой, и я бы предпочел работать только с программистами, которые знали, как работают их инструменты ...
dash-tom-bang
5

Внутренние модели данных принципиально отличаются.

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

В первых версиях SVN, если вам нужно было еще раз объединить ветвь Bс ветвью A, вам пришлось вручную указать, какой диапазон ревизий Bвы хотите объединить, чтобы избежать слияния одних и тех же ревизий дважды. Умный разработчик, конечно, будет использовать сообщение о коммите, например, «Объединено в B: 1234».

SVN 1.5 "исправил" это. Но это не изменило, как слияния применяются фундаментально. Он просто добавил некоторые дополнительные метаданные в ветку A, сообщив SVN, что редакция 1234 была объединена, и позволила SVN автоматически выбрать правильный диапазон редакций.

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

Объединение двух ветвей - сравнительно простой пример. Но воображение это более сложный сценарий

  1. Создайте ветку Aот trunkи сделайте несколько коммитов здесь
  2. Создайте ветку Bот Aи сделайте несколько коммитов здесь
  3. Сделайте несколько коммитов trunkиA
  4. Слить Bвtrunk
  5. Слить AвB
  6. Слить Aвtrunk
  7. Слияние Bс trunk(это на самом деле ничего не должно делать)

Правильная обработка этого с использованием модели метаданных становится чрезвычайно сложной (я не знаю, действительно ли SVN правильно обрабатывает этот сценарий, и я не склонен проверять это).

Обработка этого сценария в git чрезвычайно проста.

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

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

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

У меня нет опыта работы с Mercurial, но я подозреваю, что его внутренняя работа похожа на git.

Таким образом, для SVN целью проекта было создание дешевого ветвления. Но в Git это была цель дизайна - сделать слияние дешевым.

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

Пит
источник
1

Я сделал немало SVN-слияний, включая ветки разработки и выпуска. По большому счету я выжил. Слияние всегда сложно, но с DCVS обратная сторона не так уж и плоха - все локально, поэтому просто обновите до известной хорошей версии и продолжайте. В то время как с SVN много событий происходило на стороне сервера, поэтому восстановление было уродливым - обычно это было связано с стиранием локальной копии и проверкой новой чистой ветки, чтобы попробовать ее снова. В моем случае было неплохо - помогает гигабитное соединение с SVN-боксом. Но у нас было несколько подрядчиков, у которых было много проблем с этим, так как они были на медленных соединениях, так что все происходило вечно, включая слияния.

Уайетт Барнетт
источник
экстраполяция на медленном соединении, работа с удаленного удаленного сервера также приводит к ошибочным сбоям соединения при больших обновлениях> <Совсем не весело.
jxramos
-1

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

Здесь кроется одна из самых приятных вещей в git. Это не наследование DVCS, это просто то, в чем Git превосходит все. Вы можете объединить определенные ревизии из любой ветви в другую. Он в основном просто берет diff и применяет его к другой ветке, но делает отслеживание и гораздо более автоматическим.

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

Конечно, алгоритм автоматического слияния также выглядит более плавным, и git был построен с нуля на модели «сделай ветвь для всех вещей», поэтому ветвление в ней просто очень плавное и легкое. Просто кажется естественным часто ветвиться с тем, насколько легкими являются его ветви

Earlz
источник
Кроме того, я полагаю, что Mercurial имеет аналогичную функциональность
Earlz
2
На самом деле, вы можете сделать то же самое в SVN. Я делаю это все время. Команда SVN Merge может извлечь ревизию (или диапазон ревизий) из другой ветви и применить ее к своей рабочей копии, а затем зафиксировать ее.
Мейсон Уилер
2
@MasonWheeler Имейте в виду, что большая часть настроений против svn была направлена ​​на версии до 1.5 (когда svn получил отслеживание слияния). И, конечно, многое из этого - просто бессмысленный фанатизм ...
Яннис
3
@MasonWheeler см. Также stackoverflow.com/a/4215199/69742 Этот пост сводится к DVCS, отслеживает наборы изменений, а не версии . Наборы изменений по своей природе легко взять и объединить ... версии не так много, потому что они требуют контекста
Earlz
@MasonWheeler ой, а вот этот: stackoverflow.com/questions/2471606/…
Эрлз