Pull to refresh

Comments 82

Ветки в svn — это тихий ужас, лучше уж что-нибудь с нормальной нативной поддержкой веток иметь, а не эти костыли.
Юзайте git лучше.
Git/SVN это детали реализации
речь в статье о другом
Лучше уж на примере того, где это нормально реализовано, показывать, вы бы еще на CVS попытались продемонстрировать принципы ветвления.
Описанный рабочий процесс — интересный, но команды SVN для создания ветки и слияния выглядят просто жутко и отпугивают читателя. В GIT/Mercurial это просто 'git/hg merge', а все остальное система определяет автоматически.
Очень советую, попробуйте Mercurial (он проще), тем более, что он работает с централизованными репозиториями SVN.
Команды svn приведённые в статье не раскрывают всех возможностей. Всё можно сделать немного проще. Но хотелось бы посмотреть на эквивалентную стратегию в hg. Могли бы вы привести аналогичные примеры?
У нас разработка происходит примерно так
1. Создаем папку для ветки
mkdir mybrahch
cd mybrahch
2. Создаем ветку
hg clone <project_path/URL>
3. Работаем…
hg commit -m «Разработано что-то полезное»
4. Получаем последнюю версию из централизованного репозитория
hg pull <project_path/URL>
5. Объединяем
hg merge
6. Тестируем…
7. Если нашли ошибку, идем на п. 3
8. Обновляем централизованную ветку
hg push <project_path/URL>
Преимущества:
1) в SVN имя ветки должно быть уникальным для всех, в распределенных системах имя ветки локально для разработчика и после объединения и синхронизации про ветку вообще можно забыть.
2) Git/Mercurial действительно умеет очень просто объединять ветки. Я в первый раз, когда объединил две ветки, а система не задала не единого вопроса, был даже немного напуган и прошелся по всем изменениям, убедившись, что система сделала все правильно.
Недостатоки:
1) в Git/Mercurial нельзя извлекать часть репозитория, а только весь репозиторий целиком. Для очень больших проектов это может стать проблемой
2) в Git/Mercurial плохо работать с бинарными файлами из-за того, что репозиторий в этом случае будет очень быстро расти в размере. Это может тоже быть плохо для веб-проектов.
SVN и Mercurial можно использовать совместно и я слышал, что так делают. Но подробностей не знаю.
1. Создаём ветку
> svn copy ^/trunk ^/branches/name

2. Переключаемся на ветку
> svn switch ^/branches/name

3. Работаем…
> svn commit -m «Разработано что-то полезное»

4. Сливаем изменения из ствола в ветку
> svn mergeinfo --show-revs eligible ^/trunk
123
125
126
> svn merge --accept postpone -r 122:HEAD ^/trunk


5. Правим конфликты, если таковые имеются

6. Тестируем и комитим результаты слияния
> svn commit -m «Слияние trunk 123:126»

7. Переключаемся в основную ветку
> svn switch ^/trunk

8. Сливаем ветку в ствол
> svn merge --reintegrate ^/branches/name

9. Правим конфликты, но пока их тут никогда небыло и убираем изменения, которые сливать нет необходимости (например версия модуля в maven)

10. Тестируем и комитим результаты слияния
> svn commit -m «Слияние branches/name»

11. Удаляем ветку
> svn delete ^/branches/name

Шаг 3 автоматизирован.
Для шагов 7 и 8 так же есть скрипт.

Вижу, что по сравнению с hg действительно приходится делать больше телодвижений:
1. Получение версии для слияния
2. Комиты результатов слияния (2 шт.)
В hg тоже нужно комитить результаты слияния. Я пропустил этот шаг по ошибке, т.к. GUI объединяет эти два действия в одно. Если точнее, даже три действия — для редактирования конфликтов автоматически запускается Kdiff3 или любая другая объединялка.
А можно про разрешение конфликтов в Git поподробнее? Лично у меня в SVN большинство правок мержиться нормально, но иногда встает раком при изменении одних и тех же кусков разными людьми. Естественно, такие ситуации решаются только волевым вмешательством и ручным мержем. Ну и иногда у клиента из-под lin рвет башню и он за счет разных переносов строк считает конфликтным весь файл.

Я собственно к чему — есть возможность привести пример конфликтов, которые спокойно разрешает git, но не может решить svn? Хочется чужого опыта хлебнуть, а не собственные шишки на рабочих проектах набивать.
для переносов строк выставляйте autoproperties:
*.php = svn:eol-style=LF
Либо пользуйтесь параметром --ignore-eol-style при merge
За совет спасибо. Обязательно попробую. Но это трабла вылезает в худшем случае раз месяц, а то и реже.

Меня очень сильно интересует конфликты, которые git хорошо резолвит, а svn не дюжит. Просто большинство историй переходов с svn на git содержит примерно такой сценарий
1. Развернули svn
2. Криво смержили (не читали мануал)
3. Расстроились
4. Развернули git
5. Смержили правильно
6. Заклеймили SVN позором

Ну и еще некоторый процент ситуаций, где распределенное хранилище тупо удобнее централизованного. С этим понятно. А вот подтверждению сакральному «git мержит лучше, чем svn» еще не видел.
В этом то и преимущество git — нет такой необходимости читать документацию. А статьи и высказывания «Ветки в svn — это тихий ужас» уже немного задолбали.
Вы меня немного не так поняли. Под вторым пунктом я имел ввиду человеческую ошибку, совершенную как следствие начала знакомства с системами контроля версий. Которую человек с некоторой вероятностью совершил бы и работая с git.
А документацию читать надо всегда)

«Последовательность:
1. Эксперимент
2. ппц
3. Чтение документации

неискоренима»(с)
Вы описали в точности мою ситуацию (только у меня Mercurial вместо Git). При слиянии в SVN нужно задуматься, сосредоточиться и сделать. А в Git/Mercurial — просто сделать, не приходя в сознание.
Я б хотел привести конкретный пример или доказательство, но не могу — давно уже не пользуюсь SVN. Но по «ощущениям» все очевидно практически сразу, нужно пробовать.
На Хабре, кстати, есть много хороших статей по hg:
habrahabr.ru/blogs/development_tools/108443/
habrahabr.ru/blogs/development_tools/108658/
habrahabr.ru/blogs/development_tools/108904/
habrahabr.ru/blogs/development_tools/109074/
habrahabr.ru/blogs/development_tools/109203/ (слияние)
habrahabr.ru/blogs/development_tools/109428/
Бегло просмотрел топики. Может не прав, но они говорят об удобстве инструментария git по сравнению с инструментами svn. Этот тезис у меня вопросов не вызывает.
Меня больше волнует вопрос «качества» слияния. Некоторые люди говорят, что с git они реже разрешают конфликты руками. Как я вижу от ручного разрешения конфликтов в git все равно не уйти, но «приятнее» проходят. Правильно?
Да, ручных разрешений конфликтов не избежать. Они появляются тогда, когда двое или больше программистов правят одни и те же строчки кода. Если они правят файл в разных местах, то конфликт разрешается автоматически как в Git, так и в SVN, насколько я понял.
Kdiff3 (или другая графическая объединялка) как инструмент слияния конфликтных файлов удобен тем, что показывает 4 панели:
1. Версия файла, с которой вы разошлись (общая для обеих веток)
2. Ваша версия
3. «Другая» версия (из другой ветки)
4. Результат слияния (в который можно вносить любые правки)
Не подумайте, что докапываюсь, просто в одном из своих комментариев Вы написали

«Я в первый раз, когда объединил две ветки, а система не задала не единого вопроса, был даже немного напуган и прошелся по всем изменениям, убедившись, что система сделала все правильно.»

Я это прочитал как «если бы я сливал ветки в SVN, то получил бы несколько конфликтов. Но в git всё само решилось». То, что будет конфликт при совместном редактировании одной и той же строчки — тут сомнений нет. Но мне при чтении таких комментариев как у Вас виделась следующая ситуация:

SVN иногда спотыкается не только при одновременном изменении одной и той же строчки, но и некоторых других ситуациях. А git в этих ситуациях не ошибается. Есть что-то такое? Или я неверно интерпретировал Ваши слова?
К сожалению, как раз ощущение «не может быть, что оно так просто само все объединило» я рационально подкрепить не могу. Мы с сотрудником неделю работали, каждый над своим клоном, а потом я в GUI нажал на «Pull», «Merge», в визарде понажимал несколько раз на «OK» и вуаля — у меня закомиченная объединенная версия. И субъективно это воспринялось как: «Так, надо все еще раз проверить».
Это субъективное, конечно, ощущение, но вознило почти у всех наших сотрудников, когда они по-одному переходили на hg.
Я совершенно не утверждаю, что SVN хуже объединяет. Но, например, в hg нет ключа '--reintegrate'. Он будет объединять ветки в любую сторону, а потом обратно и везде с минимальным участием человека в процессе.
Спасибо за ответ. Как итог — нужно собраться с силами и самому попробовать.
Ещё интересно, как Git/Mercurial работает с tree conflicts. Это когда, например, в основной ветке фаил удалили, а в рабочей ветке в этот же фаил были внесены изменения.

И как дела обстаят с перемещениями фаилов и параллельным изменением их в другой ветке.
Насчет переименования/переноса файлов:
— В Mercurial такие операции нужно указывать явно (hg rename, если не ошибаюсь), тогда он будет отслеживать историю и конфликты правильно.
— В GIT файлы идентифицируются с помощью SHA-1, в результате, если хэши у файлов совпадают, GIT автоматически считает это одним файлом и ведет общую историю. Это называется «content-addressed storage».
Когда я выбирал VCS, я пытался «запутать» Mercurial копированиями, переименованиями и удалениями, но он со всем справился. В самых сложных случаях он спрашивал, удалить файл или оставить, если в одной ветке он редактировался, а в другой — удалился.
Ясно. В SVN проблема перемещения в том, что svn move = svn copy & svn delete
Поэтому, при редактировании удалённого фаила, после обновления или слияния старый фаил будет вновь отмечен для добавления, но на новый фаил изменения накатятся, т.е. если надо оставить новый фаил, то ваши изменения уже будут в нём.
Формально говоря это не ветка, а клон репозитория :) Механизм веток в Mercurial есть, но его использование, по-моему, более специфично, например разделение на production и stage. А собственно для разработки, да, удобнее использовать клоны.
«для разработки, да, удобнее использовать клоны.» как можно необходимость называть «удобнее»? :-)

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

А вот с бренчами удобно следовать идеологии branch per feature (featurebranches). Это, да, удобство :-)
У меня полно на винте репозиториев созданных без клонирования :) Но вот ветки в них создавать не люблю, предпочитаю сделать клона, а потом слить с origin.
Ну если доступ есть к фс другого репозитория — тогда да. Но это исключительный случай.

А по поводу клон+слив с origin — ну кому как нравится, меркуриал предоставляет выбор и спасибо ему за это :-) Лично мне нравятся именованные featurebranches
Нет, просто репозитории существуют только локально, сначала создаю «origin», а потом его клонирую :). Но вообще да, дело вкуса.По идее бранчи должны быть удобнее хотя бы тем, что не размножается всё, но вот как-то не прижились они у меня для разработки отдельных фич. Даже с именованием как-то трудности возникали :)
Кстати, 'hg share' (с включенным плагином) позволяет создать альтернативную рабочую папку (желательно в рамках одного компьютера) и экономит место. Вы комитете в одной папке, а в другой дерево истории тоже обновляется. Так можно иметь один репозиторий и одновременно несколько последних версий разных веток.
Почему вы клонирование называете «создаём ветку»?
Это специфика Mercurial (в отличе от Git). Каждый клон является «неименованной веткой» (unnamed branch). Именованые ветки для разработки конкретной функциональности в Mercurial создавать не удобно, поскольку имя такой ветки будет существавать всегда. Именованая ветка в mercurial создается для постоянных веток (типа «stable», «develop» и прочее).
1. Именованные ветки называть легко и я их создаю для каждого тикета

2. Откуда вы взяли про «неименованные» ветви? После клона вы получаете клон репозитория. Со всеми ветвями. Никаких «неименованных» не существует, вы неправильно трактуете документацию. Unnamed == неименованная ветвь, с дефолтным именем default. И это определение из документации, я считаю, не совсем корректным.

Т.к. «Clone checks out the tip of the default (aka unnamed) branch (see NamedBranches). » — это вот поведение совсем не обязательное. Вы можете не чекаутить tip дефолта. Вы можете просто клонировать и остаться на null ревизии, а ещё через -u rev вы можете чакутнуться на конкретную ревизию или бренч (а не только на unnamed)
А как вы справляетесь с тем, что 'hg branches' выдает засоренный список веток, позвольте полюбопытствовать?

По поводу неименованых бренчей я основывался тоже на документации, см. The flow of changes—big picture vs. little. Под неименованными ветками в этом разделе подразумевается короткоживущие ветки, которым специальные имена не дают и их изолируют в отдельном клоне репозитория.
Но, это терминологический спор, сути все равно не меняет. Вы тоже правы.
Я закрываю те ветки, работы в которых более не ведутся.

В произвольный момент времени у меня hg branches выводит: default, stable, пару-тройку открытых именованных.
«я основывался тоже на документации»

книжка на red-bean давно уже устарела. равно как и wiki на селенике тоже. из hg help pull уже убрали «спорные» моменты (хотя есть вероятность, что их там никогда и не было, я не видел) :-)
Недостаток 1) решается в mercurial модулем subrepo
Недостатка 2) в mercurial нет (по сравнению с Git).
Странно, а я всегда считал, что распределенные VCS плохи для работы с бинарными файлами, поскольку требут при клонировании копирования всей истории. При работе с исходнгиками в репозитории храняться сжатые дельты, поэтому он практически не растет. А для бинарных файлов дельты хранить не получиться. В чем тут отличие Mercurial от Git?
Если я правильно помню, mercurial имеет более удобный формат хранения бинарных файлов. Но в git есть repack.
Иногда этих костылей вполне хватает и все довольны. Каждому по потребностям.
Программировать тоже можно на P133, но зачем?
Вы передергиваете.
Svn и git — это не как P133 и P4.
Это два разных инструмента, развивающиеся по-разному. Хотите используйте, хотите нет.
А какая разница, касаемо описанной темы?
Избежать
Если сливать «в лоб» (sw A, merge A B) то будет очень много конфликтов, которые очень сложно разрешить
?
UFO just landed and posted this here
«до сих пор» — а с linux-way идеологией он никогда и не изменится. Пайпы — это правильно же :-)
UFO just landed and posted this here
Да я шутил изначально :-)

но всё таки с один инструмент vs много инструментов — второе более юниксвейно, ибо специфическая утилита, умеющая хорошо делать что-то одно.
UFO just landed and posted this here
UFO just landed and posted this here
С тем же самым лозунгом можно выпилить половину гнусных утилит из линукса :-)
UFO just landed and posted this here
Эти комманды — тяжелое наследие дизайна Git. Предполагалось изночально что git будет что-то вроде версионной базы данных и поверх git можно будет построить систему контроля версий (кто-нибудь помнит cogito?). Так вот — база данных гит состояла из кучки шелл скриптов которые должны вызываться твоей программой.

Но с тех пор произошло несколько коррекций
1) Git это не база данных а система контроля версий
2) API по управлению git репозиторием основанной на шелле — зло

Насчет второго — было несколько попыток сконвертировать git в библиотеку с нормальными баиндингами для других языков. Несколько попыток потерпели fail. Но вот последняя нормально развивается — github.com/libgit2 Будем надеятся что в скором времени git перейдет на нее, а комманды типа hash-object уйду в нибытие (в смысле из шелла в API).
hg — утилита, которая хорошо делает что-то одно — управляет версиями :)
Я при выборе VCS остановился на Mercurial по следующим, возможно субъективным, причинам:
1. В Git с поддержкой Windows довольно плохо.
2. К Mercurial есть плагин позволяющий хранить временные штемпели отдельных файлов — специфика конкретного проекта.
3. Ревизии Git идентифицируются хэш-идентификаторам, что не удобно для кратковременного запоминания (пусть даже и части id). В Меркуриале идентификатор состоит из локального номера и глобального идентификатора (типа 143:ab46778a...), и в 99% случаях для работы с репозиторием достаточно запоминать номера.
Сравните,
git diff as5675ff:cfg7с261
и
hg diff 100:145
А так, оба инструмента очень хороши.
UFO just landed and posted this here
пункт 3 очень важный, конечно. зачем запоминать номера ревизий?
опубликовать ссылку на проблемное место на тестовом хосте в задаче (в мегаплане или другом тасктрекере)

Не понял, что за проблемное место и откуда оно взялось?

А хуками для автоматического деплоя на все эти *.ПРОЕКТ.КЛИЕНТ.devserver.ru рекомендуете пользоваться или ручками заливать?
> Не понял, что за проблемное место и откуда оно взялось?
ссылка на страницу с исправлением/доработкой

> А хуками для автоматического деплоя на все эти *.ПРОЕКТ.КЛИЕНТ.devserver.ru рекомендуете пользоваться или ручками заливать?
правильно настроенные хуки в стократ лучше ручек
указывать -r 101:167 давно не нужно, нужно использовать --reintegrate
UFO just landed and posted this here
UFO just landed and posted this here
svnadmin upgrade

rtfm 8)
UFO just landed and posted this here
Насчет reintegrate верно написали выше (хотя указывать ревизии при мерже в бранч, думаю, надо): вливать ветку в транк все-таки обязательно нужно с помощью опции --reintegrate, а не просто merge: причина, синтаксис.
--reintegrate, если в ветке не продолжится разработка после этого
Неплохая вводная статья, особенно часть, касающаяся развертывания. Кстати, её можно было бы расширить до отдельной заметки.

Касательно ветвления, я вот тут делал перевод неплохой статьи про подход «одна ветка на одну задачу»: scm-notes.blogspot.com/2010/09/branch-per-task-workflow-explained.html

И вообще вот здесь собрал много ссылок на тему ветвления и не только:
scm-notes.blogspot.com/p/software-configuration-management.html
Почему в разделе ВЕБ-разработки? SVN используется в значительно больших местах.
> Особенностью современной веб разработки является полное отсутствие планирования при создании, поддержке и выкатке проектов.

Потому что речь идет конкретно о применении VCS в веб-разработке.
При слитии trunk в ветку необязательно указывать ревизию последнего слития, достаточно указать ревизию создания ветки.
В дополнении к уже сказанному про reintegrate: если есть необходимость поддерживать ветку дальше, то необходимо заблокировать ревизию:
> svn merge --reintegrate @branch
> svn ci -m "..."
Rev: 123
> svn sw @branch
> svn merge --record-only -c 123 @trunk
> svn ci -m "..."
Можно поподробнее? Не пойму что именно произойдет и как это повлияет на дальнейшую разработку.
«Once you have performed a reintegrate merge you should not continue to use it for development. The reason for this is that if you try to resynchronize your existing branch from trunk later on, merge tracking will see your reintegration as a trunk change that has not yet been merged into the branch, and will try to merge the branch-to-trunk merge back into the branch! The solution to this is simply to create a new branch from trunk to continue the next phase of your development.»

Так сказано по ссылке приведённой в habrahabr.ru/blogs/webdev/120063/#comment_3932020

Тем не менее параметр --record-only просто устанавливает в свойство svn:mergeinfo ревизию транка, в которой были слиты изменения из ветки, без слития самих изменений и в дальнейшем merge не будет учитывать эту ревизию при слитии транка в ветку.

> cd my-calc-branch
> svn propget svn:mergeinfo .
/trunk:1680-3305

# Let's make the metadata list r3328 as already merged.
> svn merge -c 3328 --record-only ^/calc/trunk
> svn status
M .

> svn propget svn:mergeinfo .
/trunk:1680-3305,3328

> svn commit -m "Block r3328 from being merged to the branch."

Пример взят по ссылке svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html которую я крайне рекомендую для ознакомления всем, кто так или иначе работает с ветками SVN.
Спасибо, теперь понятно. Подобные действия обычно производил ручной правкой svn:mergeinfo.
Рад, что чем-то помог. Но всё-так советую почитать документацию и вполне возможно, что найдёте ещё много полезного.
Спасибо, но уже поздно читать документацию по svn, т.к. мы намучились с ветками в нем и уже начали переход на hg.
Ветка создается очень просто:

svn copy svn://svnserver.ru/КЛИЕНТ/ПРОЕКТ/trunk svn://svnserver.ru/КЛИЕНТ/ПРОЕКТ/branches/НАЗВАНИЕ_ВЕТКИ -m 'КАКОЙ ТО КОММЕНТАРИЙ О ВЕТКЕ'


Позабавило :) по сравнению с
git branch НАЗВАНИЕ_ВЕТКИ
svn copy ^/trunk ^/branches/branch_name
Согласитесь, не намного сложнее?

Да и никто не мешает сделать скрипт, наподобии:
svn copy ^/trunk ^/branches/%1

И вызывать его:
svn_branch НАЗВАНИЕ_ВЕТКИ
Особенностью современной веб разработки является полное отсутствие планирования при создании, поддержке и выкатке проектов.


Дальше можно не читать.
Sign up to leave a comment.

Articles