Каковы преимущества Mercurial или Git над SVN для ветвления / слияния?
Я слышал, например, что слияние веток с git или mercurial проще, чем с svn.
Читая в прошлый раз Джоэла о программном блоге, я не понял, почему. Не могли бы вы привести конкретный пример, где слияние с git/mercurial приводит к меньшему количеству конфликтов слияния по сравнению с svn, пожалуйста?
3 ответа
Один простой пример - git может автоматически преобразовать слияние в "ускоренную перемотку вперед". Например, допустим, у меня есть ветка, которая выглядит так:
Мастер:
A ---> B ---> C
И я создаю функциональную ветку на основе Master с новыми коммитами D и E.
Особенность:
A --- > B ---> C
\
D ---> E
В svn, когда вы объединяете ветвь объектов обратно в master, вы должны создать совершенно новый коммит, который применяет изменения D и E в Master. Итак, это выглядит так:
Master:
A ---> B ---> C -----------------> F
Feature: \ /
---> D ---> E -->
В git у нас есть выбор, как включить функцию ветвления в master. Если мы сделаем
git rebase feature
Git автоматически распознает, что это тривиальное слияние, и выполнит ускоренное слияние, которое добавит новые коммиты в основную ветку. Результат перебазирования:
Мастер:
A ---> B ---> C ---> D ---> E
И голова Мастера, и Особенность указывают на коммит E (другими словами, они выглядят совершенно одинаково). Быстрое слияние аналогично тому, что происходит при обновлении в SVN.
Кроме того, у вас есть возможность заставить git создать коммит слияния. Если вместо этого мы делаем:
git merge feature
git создаст коммит слияния. Результатом слияния является:
Master:
A ---> B ---> C -----------------> F
Feature: \ /
---> D ---> E -->
Фиксация F является комбинацией D и E.
Проверьте HGINIT. Это статья / учебник Джоэла Спольски (не его последняя запись в блоге) на эту тему. Вы можете найти часть Subversion Re-Education особенно интересной.
Subversion удобно реализует только одну концепцию - ветви страха. Это означает, что одна ветвь всегда parent
а другой feature
, Функция может извлекать обновления у родителя с течением времени (слияние), но родитель может извлекать изменения функции только один раз (слияние - реинтегрировать), и тогда дочерний элемент должен быть закрыт. Этого достаточно во многих случаях, но не всегда. Не все ветви являются функциональными. У меня есть пара примеров.
- Первый. Хорошим примером является
release branch
, Предположим, вы готовите релиз на основе тщательно протестированной версии ствола. Вы делаете ветку релиза из желаемой версии ствола. Теперь на вас не влияют никакие последующие модификации ствола. Но вы можете захотеть добавить исправления в ветку релиза, и вы можете захотеть перенести их в магистраль, не закрывая ветку релиза. Это не может быть реализовано с помощью ветвей функций svn. С svn вам придется подождать, пока ветка релиза больше не понадобится, а затем реинтегрировать ее. Или сделать бэкпорт исправлений вручную. - Во-вторых. Отраслевые или разработчики. У вас нет готового примера того, когда они действительно полезны, но вам точно не понравится их в SVN. Будет больно синхронизировать такие ветки.