Насколько я понимаю, SVN «Легко разветвляться. Сложно объединить ». Это почему? Есть ли разница, как они сливаются?
Пожалуйста, смотрите мой ответ Переполнение стека для очень конкретной ситуации, когда Mercurial (и Git) сливается без проблем, и где Subversion представляет вам фиктивный конфликт. Ситуация - это простой рефакторинг, выполняемый в ветке, где вы переименовываете некоторые файлы.
Что касается ответа tdammers, то здесь есть ряд недоразумений:
Subversion, Mercurial и Git отслеживают моментальные снимки проекта в масштабах репозитория. Называть их версиями , ревизиями или наборами изменений не имеет значения. Все они являются логически атомарными снимками набора файлов.
Размер ваших коммитов не имеет значения, когда дело доходит до слияния. Все три системы объединяются с помощью стандартного алгоритма трехстороннего объединения, и входные данные для этого алгоритма
Это не имеет значения , как были созданы две версии ветви. Вы можете использовать 1000 небольших коммитов начиная с версии предка, или вы можете использовать 1 коммит. Все, что имеет значение, является окончательной версией файлов. (Да, это удивительно! Да, многие руководства DVCS делают это ужасно неправильно.)
Он также поднимает некоторые хорошие моменты о различиях:
В Subversion есть некое «вуду», из которого вы можете слиться /trunk
, скажем, в /branches/foo
. Mercurial и Git не используют эту модель - вместо этого ветки моделируются непосредственно в истории. Поэтому история становится ориентированным ациклическим графом, а не линейным. Это гораздо более простая модель, чем та, которая используется Subversion, и это отсекает ряд угловых случаев.
Вы можете легко отложить слияние или даже позволить кому-то другому справиться с этим. Если у hg merge
вас возникнет масса конфликтов, то вы можете попросить своего сотрудника hg pull
от вас, и тогда у него точно такое же состояние. Так что он может hg merge
и, возможно, он лучше разрешает конфликты, чем вы.
Это очень трудно с Subversion, где вам необходимо обновить, прежде чем вы сможете зафиксировать. Вы не можете просто игнорировать изменения на сервере и продолжать фиксировать в своей собственной анонимной ветке. В общем, Subversion заставляет вас играть с грязной рабочей копией, когда вы svn update
. Это довольно рискованно, поскольку вы нигде не хранили свои изменения в безопасности. Git и Mercurial позволяют сначала фиксировать, а затем обновлять и объединять по мере необходимости.
Реальная причина, по которой Git и Mercurial лучше объединяются, чем Subversion, заключается в реализации. Существуют конфликты переименования, которые Subversion просто не может обработать, даже если понятно, что правильный ответ. Mercurial и Git легко справляются с этим. Но нет никаких причин, по которым Subversion не могла справиться и с этим - централизация, конечно, не причина.
trunk
в SVN. С DVCS вы можете фиксировать без совместного использования, но в SVN выsvn commit
будете напрямую влиять на тех, кто работает в той же ветке. Даже если мы вдвоем работаем над веткой в SVN, я не могу зафиксировать свою работу без необходимости немедленно сливаться с вашей работой. Это делает коммиты несколько пугающими - а это страшное свойство для системы контроля версий! :-)Основная проблема заключается в том, как эти системы представляют версионную структуру каталогов.
Основная концепция Subversion, вокруг которой вращается вся система, - это версия (или, в svn lingo, «revision»): снимок файла в определенной точке. Пока история совершенно линейна, все в порядке, но если вам нужно объединить изменения из двух независимых линий разработки, svn должен сравнить текущие версии обеих версий, а затем провести трехстороннее сравнение между последней общей версией и две версии головы. Линии, которые кажутся измененными в одной из голов, но не в другой, могут быть легко решены; линии, которые одинаково отклоняются в обеих головках, более жесткие, но обычно выполнимые; линии, которые отличаются по-разному, заставляют svn сказать: «Я не могу понять это, человек, пожалуйста, разреши это для меня».
Напротив, git и mercurial отслеживают изменения, а не версии. Весь репозиторий представляет собой дерево наборов изменений, каждое из которых зависит от родителя, где родительский набор изменений может иметь любое количество дочерних элементов, а корень дерева представляет собой пустой каталог. Другими словами, git / hg говорит: «сначала у меня ничего не было, затем был применен этот патч, затем этот патч и т. Д.». Когда вам нужно объединить две линии разработки, git / hg не только знает, как выглядит каждая голова в данный момент и как выглядела последняя распространенная версия, но и знает, как произошел переход, что позволяет осуществлять более умное слияние.
Еще одна вещь, которая облегчает объединение в DVCS, является косвенным следствием разделения концепций коммита и толчкаи разрешать всевозможные перекрестные слияния между любыми двумя клонами одного и того же хранилища в любое время. С svn люди, как правило, фиксируют большие наборы изменений с часто не связанными изменениями, потому что фиксация также является обновлением в центральном хранилище, которое затрагивает всех остальных членов команды; если вы совершите испорченную версию, все будут сердиться на вас. Поскольку в большинстве установок используется сетевой svn-сервер, фиксация также включает в себя перекачку данных по сети, что означает, что фиксация вносит значительную задержку в рабочий процесс (особенно, когда ваша рабочая копия устарела, и вы должны сначала извлечь). В git и mercurial фиксация происходит локально, и поскольку обе они очень эффективны при работе с локальными файловыми системами, обычно они завершаются мгновенно. В результате люди (как только они привыкнут к этому) совершают небольшие постепенные изменения, а затем, когда это работает, толкать дюжину или около того совершает за один раз. Затем, когда наступит время слияния, SCM будет иметь гораздо более подробную информацию и сможет лучше и эффективнее решать конфликты безопасно и автоматически.
И еще есть приятные детали, которые делают вещи еще проще:
источник
hg mv
илиhg addremove --similarity...
), в то время как Git использует эвристику, но обе обрабатывают переименования . Я могу получить конфликт дерева даже с разницей в 1 строку в объединенных файлах! Вы должны заново изучить некоторые аспекты Subversion, извините.rename a b
какcopy a b; remove a
и обе делают это за один атомный коммит. Различие в поведении слияния связано с различной обработкой угловых случаев и с Subversion, допускающим больше слияний, чем Mercurial и Git. Наконец, Git обнаруживает переименования во время слияния и регистрации - мы думаем добавить это и в Mercurial.