Честно признаюсь, что долго не понимал, о чем идет речь, когда Subversion ругают за проблемы со слияниями бранчей. До сегодняшнего дня, когда мы на работе огребли довольно объемную проблемку. Хочу поделиться подробностями.
Есть у нас средних размеров джанговский проект — "Куда Все Идут". В нем изначально, из-за нежелания плодить без надобности сущности, было одно глобальное приложение под неоригинальным названием "core". Недавно из-за разрастающихся планируемых фич нам захотелось разделить код на три приложения. Два со специфичной логикой — "social" и "content" — и одно с общей для всего проекта логикой — все тот же "core". Причем прямо сейчас часть "content" будет практически пустой, и по сути весь процесс заключается в отпочковывании части "social" от части "core".
При это мы находимся в такой ситуации, когда заморозить текущую разработку на месяц-другой нельзя, и поэтому мы решили сделать это разделение в отдельном бранче.
У нас получается, в итоге, два бранча:
Бранчи, безусловно, обязаны сильно разойтись, но ведь на то нам и нужна система контроля версий, чтобы это разруливать.
И вот сегодня под вечер, когда magicsplit достиг своего работоспособного состояния, мы решили его влить в транк.
offline/trunk$ svn merge -r1489:HEAD https://.../magicsplit/ .
И накнулись на интересные, но от того не менее больно бьющие по лбу грабли.
Практически первое, что было сделано в magicsplit — это рядом с "core" была создана папка для нового приложения ("social"), в которую тут же был унесен практически весь код, который к этому приложению по логике относился. В частности, некоторые модели данных, практически все view'хи и шаблонные теги переехали в эту новую директорию. Дальше там происходила практически только отладка. А в это время в транке этот же самый код активно правился. Но в старых файлах внутри core.
Так вот, засада заключается в том, что Subversion, хоть и номинально знает, что, например, social/views.py переехал туда из core/views.py, никак эту информацию при слиянии не использует. И поэтому у нас слияние бранча оказалось практически пустым: изменения из транка влились в оставшуюся core/* и никак не слились с бранчевыми изменениями в social/*.
Теперь, вот, не знаем, что делать. Варианты пока такие:
Что посоветует уважаемое сообщество?
Комментарии: 39
Базаар - весьма глючная и тормозная хрень. Бери git, он специально для такого и создавался (трекает контент вцелом, а не пофайлово, т.е. знает что файл переехал в другую папку и сумеет примерджить изменения).
Или Hg/mercurial (который, вроде, слизан с гита, но, говорят, медленнее и сложнее в использовании).
Олег, у тебя наверное данные примерно годовалой давности. Он сильно изменился с того времени. Кроме того, мне нужна от него вот эта одна конкретная вещь.
Думал про это. Пока меня пугает то, что его надо долго изучать, чтобы начать пользоваться. А нам, по сути, это надо завтра :-). Кроме того, слышал, что ммпортом из svn у него какой-то убогий. Или нет?
Оба утверждения убивают наповал.
Mercurial, как и Bazaar, написан на питоне, поэтому нет ничего странного что git быстрее примерно в два раза. Но велика ли разница длится коммит 1 секунду или 2-е? :)
У меркуриала мне нравится что ссылка на репозитарий и веб-морду одна.
Я бы попробовал на скорую руку посмотреть на результат применения bzr.
Насчет быстродействия: если я правильно помню, то ставка у bzr была именно на юзабилити (и таки да, использовать его из консоли оказалось приятнее чем тот же svn), а потом догонялась скорость (начиная с версии 0.9 она заметно выросла; текущая - 1.6). Но скорость операций для проектов (в моем случае - на rails) меня устраивает более чем.
Насчет скорости - сравнение.
Попробуй git-svn -ом выгрузить весь свой репозитарий и сделать слияние уже гитом. git должен корректно разрулить все перемещения файлов и смердживание бранчей даст то, что нужно.
На всякий случай уточню: git от svn отличается помимо прочего еще и тем, что работает не с "рабочей папкой", а с локальной версией репозитария, т.е. вся история изменений доступна локально без сервера. А git-svn умеет выгружать и загружать все это с/на сервер svn.
Попробуйте у народа с reactos.org спросить, они периодически с бранчами балуются.
В два раза - это вы сами придумали? Тесты говорят совершенно о другом.
<p>Ситуация вообще очень неприятная. Кстати, о проблемах, которые возникнут у тех, кто захочет переименовывать и перемещать файлы в ветке, предупреждают и сами разработчики subversion вот тут: http://svnbook.red-bean.com/ в главе 4, в п. "Merges and Moves"</p> <blockquote> <p>The moral of this story is that until Subversion improves, be very careful about merging copies and renames from one branch to another.</p> </blockquote> <p>Получается, в рамках subversion нет другого способа, кроме как вручную перенести все изменения. Конечно, не совсем вручную ...</p> <p>Если бы меня заставили заниматься такими вещами, то я бы сделал примерно так:</p> <ol> <li> <p>Перенес все изменения, сделанные в trunk-е, в ветвь. Упростить себе жизнь можно, воспользовавшись svn merge для каждого файла или каталога в отдельности, для чего перейти в каталог branches/magicsplit/social рабочей копии и выполнить в ней <em>svn merge svn://.../trunk/core@START svn://.../trunk/core@END</em>. Это сделает diff для изменении и применит его к текущему каталогу.</p> </li> <li> <p>Перенес все изменения (вместе с изменениями, сделаннами в ветви) обратно в trunk. Перейдя в trunk рабочей копии, выполнить<br /> <em>svn merge svn://.../branches/magicsplit@START svn://.../branches/magicsplit@HEAD</em>. Здесь START - это номер ревизии, начиная с которой произошло отпочкование.</p> </li> </ol> <p>Я совсем не уверен, что этот способ будет наилучшим или вообще подходящим для вашего случая.</p>
А можно попробовать svn 1.5 — там сильно починили merge-tracking и branch-merging.
Вообще, перемещения файлов должны учитываться в svn при мерже. По крайней мере, у меня учитывались.
Попробуйте поменять trunk так, чтобы по структуре файлов эта ветка максимально походила на новую. Убедитесь, что работает (а лучше зарелизьтесь), а после можно и смержиться в полуавтоматическом режиме.
Могу попробовать сделать это через GIT. Поставил выкачиваться репозиторий :)
Mercurial, на мой взгляд, с задачей вполне справляется.
Я как-то делал слияние веток в SVN под Windows с помощью TortoiseSVN. Там неплохой мануал как это лучше делать: http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-dug-merge.html
Там два способа в зависимости от особенностей организации репозитария (портируются ли изменения транка в бранч). Оба основаны на получении патча с изменениями бранча, применения его к коду транка локально, фикса конфликтов и тестирования, а потом коммита в транк. В TortioseSVN это делается легко, как описано по ссылке. И т.к. пути можно указывать произвольные при создании дифа и при применении патча к локальной копии транка, то можно разбить задачу на части — для каждой перемещенной папки или файла, если их путь поменялся.
Я могу ошибаться, но мне кажется автоматическое отслеживание перемещений директорий и файлов при слиянии веток — это задача программиста а не системы контроля версий и автоматизировать ее нормально невозможно и не нужно. Иначе система теряет примитивность и предсказуемость.
Это смысл любого слияния, как такового. Проблема этого случая в том, что слияния по сути не происходит.
Я бы не согласился с однозначностью вывода. Если система контроля версий может это сделать надежно и предсказуемо, то пусть делает. Никакой особенной rocket science я тут, признаться, не чувствую. Это просто вопрос аккуратного программирования логики.
Собственно, как написал выше ods, Меркуриал с этим справляется, по крайней мере в простых случаях.
Про способ Романа... Я так понимаю, если изменения транка портированы в бранч (один из способов по ссылке), то потом надо сделать дифф между текущим транком и текущим бранчем и применить его к транку, но не диф между точкой отпочкования и текущим бранчем т.к. он будет содержать уже содержащиеся в транке изменения.
На части разбивать, с учетом переноса файлов.
Да, уже почитал, интересно работает ли это в реальной жизни у кого-нибудь.
Предыдущий коммент про способ Романа, это я не въехал, наверно предлагается полностью заменить транк бранчем (если перенести рефакторинг из бранча в транк сложнее, чем перенести новые фичи из транка в бранч). Но тогда второй шаг все равно странно выглядит.
Посмотрите svnmerge.py (http://www.orcaware.com/svn/wiki/Svnmerge.py)).
Или сразу svn 1.5 (у которого сейчас RC8) - там со слиянием намного лучше (уж перемещаемые файлы в бранчах он точно отслеживает), но почти все тоже самое можно делать и с svnmerge.py в 1.4.
Спасибо за замечания. Действительно, предлагалось именно перенести все изменения в бранч, а потом просто заменить trunk. И действительно, второй шаг делает совсем не то, что нужно. Вместо этого ...
или сказать
Мне в свое время, чтобы не попадать в такие ситуации, очень помог совет в конце http://svnbook.red-bean.com/en/1.1/ch04s04.html#svn-ch-4-sect-4.4, когда бранч какой-то фичи долго разрабатывается, то установить в команде период а лучше день, скажем раз в неделю, когда все изменения транка портируются в бранчи. Тогда по завершению жизни бранча вообще нет проблем, сразу шаг 2.
Я боюсь, что нам бы это не помогло. Проблему вызывает не то, что бранч долго разрабатывается (сами изменения кода там как раз не конфликтуют почти), а то, что в бранче основной код переехал в другие файлы. Поэтому как только это переименование случилось — все, никакие изменения из транка автоматически в бранч попадать не будут.
А если рассуждать о том, как надо было, то надо было сделать максимум изменений без двигания структуры файлов, потому на день прекратить разработку в транке, сделать все переносы и тут же слить.
А тут автоматически и не получится в общем случае. Чтобы начать портировать коммит из транка, можно его выгрузить как контекстный дифф для каждого измененного файла, а потом применить полученные патчи к файлам бранча, в которые соответствующий код переехал. Не совсем автоматически, но и не в ручную.
Угу. Вот похоже (после сегодняшних проб), так и придется сделать. Я еще напишу результаты отдельным постом.
Разве не проще было сделать SVN -> GIT -> merge -> SVN?
У нас на проектах сливались обе ветки к себе на локальную машину и каждый мёржил своё код в Araxis Merge. Да, не очень быстро, зато потом баги фиксить меньше. С автоматикой перед этим натерпелись…
У гита сейчас лучший импорт (и заодно экспорт) из svn.
Просто хочется плакать... :'( Читайте#History) и просвещайтесь.
Посоветую изначально пользоваться SCM, которые понимают, что такое бранчи. В противовес SVN, который думает, что бранч это другой проект в директории рядом.
То есть git/Mercurial. Про Bazaar/darcs/arch ничего не скажу, не пользовался, не слышал.
У git кривой импорт из svn. Бред.
Да, Mercurial медленнее, чем git, ибо писан не полностью на Си, а на Python с небольшой вставкой Си по поводу диффа. А вы разницу заметите? Вместо 380 ms оно будет мержится 540. Тоже мне проблема. Конечно, цифры писать глупо, но порядок именно такой.
P.S.: реалтайм предпросмотр сообщения — это 5.
Есть предложение другое: попробовать использовать в branches svn:externals с фиксом до нужной ревизии (например, core -r4545, DAOs -r5000) на базовые или core части trunk'а.
Уточню ссылку Романа про Merges and Moves: http://tinyurl.com/36lt5n
Аналогично пытался объединять с помощью toroiseSvn две разные. В принципе слил. В принципе без косяков. Но было очень много ручных операций и после мержа при попытке сделать update/commit svn сказал что эти файлы уже есть в основной ветке. Для меня это было сюрпризов ) Надо потренироваться на кошечках )
иван, чем закончилась эпопея?
Я пока не знаю даже, закончилась ли она. Потому как ушел в отпуск :-). Но я не забуду позже написать, в любом случае.
Не знаю для меня merge в SVN самое больное место. После нескольких засад, делаю по следующему алгоритму.
Делаю checkout в пустую папку, и ручками с помощью WinMerge утверждаю изменения, потому как достало его автоматическое слияние, которое кроме проблем ничего хорошего не делает. Хотелось чтобы тортилка сам спрашивала как мерджить без попыток сделать самой, но как это сделать пока не нашол.
Вот такой велосипед.
Попробуй SVK - это VCS работающий с репозиторием Subversion, но децентрализованый и с более продвинутым merge.
Вышло 1.5 ) Пока не пробовал, но судя по комментариям, тама ситуация с мержом исправлена ) Пока делаю попытки установить 1.5
В 1.5 наконец то используется сторонняя SASL библиотека, и это счастье. Всем разработчикам так желаю делать изначально, а не впаривать CRAM-MD5 ибо остальное было делать лениво. Про мержи, правда, ничего сказать не могу : )
Итак, я обещал написать, чем все дело кончилось. Кончилось благополучно, мы живем с новым транком, но в итоге пришлось все сливать вручную. А именно: делать diff'ы по одним кускам кода и применять их к тем же кускам кода, которые в бранче переехали на новое место.
Пробовали сначала сливать автоматически, импортировав историю из svn в git и в bzr. Первый отказался сливать бранч совсем, сказав про множество переименованных файлов что-то в духе "файл перемещен, поэтому мерджить в него ничего не могу". Bzr сделал попытку все смерджить, но результатом стали обширные конфликты на весь файл в духе "а вот тут весь файл стерт был у вас в бранче, а в транке в него что-то добавлялось". Есть теория, что ни тот, ни другой не справились с задачей, потому что зависели от истории svn, где переименование не настоящая операция. Возможно, что если бы что-то такое делалось сразу под управлением git/bzr/hg, то проблемы бы не было (как тут в комментариях и показывали уже).
В сухом остатке — выработанные правила гигиены работы с бранчами в svn: если задумали менять структуру директорий, заморозьте ненадолго разработку в транке, поменяйте структуру, а уже потом бранчуйтесь и меняйте код в файлах на новых местах. Иначе оно не сольется.
После всех этих приключений вы так и остались на svn?
У меня ща примерно такие же проблемы возникли, нужно слить 2 сильно разошедшиеся ветки в ствол. Svn первый год только используем, всех заковык не знали, особо про синхронизацию со стволом! Делали, отпочковали ветку и давай в ней работать а на ствол забили, естественно в другой ветке изменения тоже никто не синхронизировал.
Вот вопрос у меня, может перейти на git/bzr/hg? или оно того не стоит, раз уже в svn засели?
Да, мы на svn. По сути-то получается, что те изменения, которые мы делали, не могла бы автоматически слить наверное ни одна система контроля версий. Хотя, возможно, и было бы полегче.
На самом деле многие разработчики у нас активно сидят внутри своих команд на bzr и git (про эти точно слышал, про hg еще нет). Но в корпоративный svn все равно все должно попадать.