Добрейшего.
Я не сторонник распределенных систем контроля версий, однако соглашусь с недавно переведенной статьей о ветвлении: несомненной заслугой распределенных систем контроля версий является то, что они открыли людям глаза на хорошие практики ветвления и слияния. При всей распространенности того же SVN, в нём ужасно реализованы ветки. Точнее, их и ветками нельзя называть - там, по сути, отращивается новое дерево файлов, мрак в общем, на мой взгляд.
Не удивительно, что стали появляться и вменяемые руководства по практикам ветвления для новоиспеченных лидеров рынка - в первую очередь git и Mercurial. На одно руководство я уже ссылался. Не прошло и года, как я наткнулся на ещё одно руководство: A successful Git branching model.
Что сказать - по наглядности переплюнуло всё, что я видел. Можно просто глянуть на картинки и посмотреть на нужные команды - и всё. Комментарии автора лишь связывают всё воедино. Читать/смотреть в обязательном порядке.
В принципе, если git заменить на другое название системы контроля версий - хуже не станет, практики проиллюстрированы базовые до неприличия. Однако в данном случае подкупило то, как именно они проиллюстрированы :)
В общем, enjoy.
Update 1. PDF-версия.
Update 2. Обсуждение на Хабе закинутой ссылки, есть пара занятных ссылок.
Update 3. Хороший перевод статьи.
Приветствую,
ОтветитьУдалитья немного поразмышлял на эту тему, со своей колокольни, вот такие мысли.
Ветвление оно же не само по себе нужно, а для достижения какой-то цели.
Рассмотрим типичные сценарии в одном из моих проектов. Характериcтики проекта - шесть разработчиков, SVN, Scrum, Test Driven Development.
В trunk у меня сейчас B84 ( следующая версия), B83 - в branches ( текущая версия, предрелизное состояние), B82, B81 - в tags.
1) Новая задача для B84. Разработка, unit-тесты проходят - commit в trunk. И так НЕСКОЛЬКО раз. Тесты и функциональность наращиваются постепенно, однако в любой момент времени тесты проходят.
2) Фикс для B83. Разработка, unit-тесты проходят - commit в branches\B83 + merge с trunk
3) Фикс для B82. Ветка в branches\B82.2, Разработка, unit-тесты проходят - commit в branches\B82.2 + merge с trunk и branches\B83
Сценарий типа (3) редок, и в 99% запускается только серьезных дефектов - мы выпускаем версию раз в 1-2 месяца, так что клиент в большинстве случаев может дождаться следующей версии (а раньше выпускали версию вообще раз в две недели, отсюда такие номерки).
Я тут пока не вижу необходимости использовать подход одна ветка - одна задача.
Другое дело, если
a) Версии редки
б) Не покрыты unit-тестами
в) Существуют масса параллельных разношерстных версий
Здесь ситуация другая - сommit в trunk потенциально приводит к проблемам, тестов-то нет. Ковыряться с кучей коммитов по одной задаче чтобы сделать merge в другую версию системы - удовольствие ниже среднего. И вот "одна ветка - одна задача" работает хорошо.
Добрейшего.
ОтветитьУдалитьВ общем-то, если убрать из приведенного в комменте описания branches и tags, то остальная разработка на транке как раз в статье про ветку-на-задачу и описывается. И поскольку используется TDD, то в статье можно убирать куски текста про поломку отстройку и функционала (таких больше половина). Однако остальные возражения остаются в силе - "стрельба по движущейся мишени", "независимость задач", "ветки как единица изменения" и "улучшенное отслеживание".
Общий смысл - в большем контроле нам теми изменениями, которые вносятся. Самый простой пример - нельзя сказать по отдельно взятому коммиту на транке, зачем он был сделан. А имея ветку, привязанную к задаче, подобный вопрос вообще не ставится.
Однако, соглашусь, что всё хорошо в меру. Я, к примеру, точно также разрабатываю на транке :) Просто потому что code owner на конкретном проекте - это только я один, я могу позволить себе коммитить непрерывно по мере выкладывания проекта на живой работающий сайт. Но как только один файл начинает правиль больше, чем один человек - ветки неизбежны.
Кстати, по описанной организации работы - вопрос небольшой. Зачем разделять бэйзлайны между branches и tags? Ведь в SVN меток в традиционном понимании вообще нет и то, что называется метками - по сути те же самые ветки. Так не проще ли на каждый релиз (он же и бэйзлайн) почковать только ветки, без переноса в tags?
>Самый простой пример - нельзя сказать по отдельно взятому коммиту на транке, зачем он был сделан.
ОтветитьУдалитьУ нас к каждому commit прилагается комментарий типа:
view Importance & Budget
[url задачи в трекере]
Такой комментарий генерируется системой управления проектами, при закрытии задачи этот текст переносится в комментарий к commit. Никаких проблем с этим никто не испытывает, в том числе и при определении впоследствии, зачем был сделан тот или иной коммит.
>Я, к примеру, точно также разрабатываю на транке :)
Дык :) Смысла особого нет в таком частом бранчевании. Я вот на текущую версии сгенерировал 40 задач при ручном тестировании сборки, всего в трекере 160 задач на версию. Обычно их поменьше, конечно, у нас просто система управления проектами позволяет делать задачи неограниченной вложенности, декомпозиция увлекает. Но те 40 задач, о которых я сказал, все равно имели бы место.
>Зачем разделять бэйзлайны между branches и tags?
Э-э, я вот написал это а потом сам долго думал. Ночью :)
В tag делается копия по выпуску чтобы знать точный состав выпущенной версии. Копия делается автоматическим построителем сборки.
>Так не проще ли на каждый релиз (он же и бэйзлайн) почковать только ветки, без переноса в tags?
Ну вот у меня был выпущен B82, при выпуске сделана копия в tags. Были бы метки - поставили бы, конечно, метку. Теперь мне надо задним числом пофиксить что-то. tags\B82 - это уже своего рода "эталон", его трогать не нужно. Делается копия в branches и с нее начинается работа.
Прокомментирую чуть позже в комментах к http://scm-notes.blogspot.com/2010/09/branch-per-task-workflow-explained.html
ОтветитьУдалитьпотому как обсуждение касается веток, а не конкретно git :)
Не очень понятно, как организовать совместную работу нескольких человек над одной задачей.
ОтветитьУдалитьс
$ git remote add bob /home/bob/myrepo
все понятно. Но это если они все на одной машине работают. А если нет ?
посмотрим, может быть комменты читает кто-то из гитофанатов :)
ОтветитьУдалитьВ результате чтения различных материалов у меня сложилось ощущение, что "ветка-на-задачу" vs "все в trunk" это священная война типа Windows/Linux, Canon/Nikon.
ОтветитьУдалитьСм. к примеру
http://martinfowler.com/bliki/FeatureBranch.html
Тут Мартин приводит аргументацию в пользу работы на trunk при условии CI. И я с ним совершенно согласен. Внедряю, кстати, у себя CI.
Ну т.е. все зависит от условий, для одного проекта выгодна практика Feature Branches + интегратор, для другого - CI/TDD + работа trunk + ветки по мере необходимости.
Спасибо за наводку - прочитаю, обязательно отпостю в бложик с комментами.
ОтветитьУдалитьОднако, после его предыдущих высказываний про контроль версий:
http://scm-notes.blogspot.com/2010/02/versioncontroltools.html
отношусь к нему с настороженностью :)
> сложилось ощущение, что "ветка-на-задачу" vs "все в trunk" это священная война
ОтветитьУдалитьда, местячковый такой холиварчик :)
> Однако, после его предыдущих высказываний про контроль версий:
ОтветитьУдалитьhttp://scm-notes.blogspot.com/2010/02/versioncontroltools.html
Я там оставил комментарий :)
> да, местячковый такой холиварчик :)
Почему, вполне себе планетарного масштаба.
> Почему, вполне себе планетарного масштаба.
ОтветитьУдалитьНу в том смысле, что узконаправленный :)
>Общий смысл - в большем контроле нам теми изменениями, которые вносятся. Самый простой пример - нельзя сказать по отдельно взятому коммиту на транке, зачем он был сделан. А имея ветку, привязанную к задаче, подобный вопрос вообще не ставится.
ОтветитьУдалитьВот тут надо понимать: зачем оно нам в истории? Т.е. нужна ли в СКВ более гранулярная история изменений чем в багтрекере?
Вот например: делаю я фичу и натыкаюсь на баг, я его оформляю отдельным коммитом и выделяю топик ветку с записью в багтрекере.
ИМХО более мелкая история нужна только девелоперу. Да и как к ней просто достучаться? Все топик бранчи оставлять?
> Т.е. нужна ли в СКВ более гранулярная история изменений чем в багтрекере?
ОтветитьУдалитьЯ скажу так - чем больше народу изменяет один элемент за единицу времени, тем нужнее.
При мер из моей практики - 20-30 человек интенсивно работают с 20-30 файлами. Каждый файл изменяется ежедневно на пиках активности по десятку раз. Иногда функционал в отдельных файлах ломался - и тогда было делом пары команд describe (речь про ClearCase) для отдельных версий, чтобы восстановить последовательность действий - кто поломал, по какому запросу на изменение, какую дельту он внёс и на каком бэйзлайне базировал свои изменения.
В общем, есть целый класс случаев, когда гранулярность коммитов надо отслеживать.
> Все топик бранчи оставлять?
не совсем понял - что такое "топик ветка"?
> когда гранулярность коммитов надо отслеживать.
ОтветитьУдалитьпардон, "когда гранулярность коммитов важна".
>При мер из моей практики - 20-30 человек интенсивно работают с 20-30 файлами. Каждый файл изменяется ежедневно на пиках активности по десятку раз.
ОтветитьУдалитьИнтересно, а что за файлы такие ?
Например, исходники медиаприложений для мотороловской платформы P2K в пору её расцвета. Я как раз на направлении Multimedia и работал СМ-инженером. Одна из самых больших компонент/команд была, отсюда и СМщиков было в лучшие времена - около десятка.
ОтветитьУдалить>Я скажу так - чем больше народу изменяет один элемент за единицу времени, тем нужнее.
ОтветитьУдалитьЯ говорю о том, чторезультатом работы девеловера над задачаей в багтрекере является 1 коммит, а не их последовательность. Если в результате работы возникло что-то, что хочется отдельным коммитом, то на него надо завести таску в багстрекере.
>В общем, есть целый класс случаев, когда гранулярность коммитов надо отслеживать.
Только 1 коммит - 1 таска в трекере.
> Все топик бранчи оставлять?
не совсем понял - что такое "топик ветка"?
Feachure branch, ветка в которой разраб изолированно от других решает свою небольшую задачу.
> Я говорю о том, чторезультатом работы девеловера над задачаей в багтрекере является 1 коммит, а не их последовательность.
ОтветитьУдалитьВот тут не соглашусь по принципиальному соображению - коммититься, т.е. создавать новые версии, надо тогда, когда для этого есть необходимость. Т.е. я начал работу над задачей, расчитаной на 12 человеко-часов и работа моя разобьется на 2 дня. Значит ли это, что мне надо "терпеть" и копить изменения, чтобы потом всё закоммитить одним движением? Никак нет - это просто опасно с точки зрения сохранности данных, не говоря уже о рабочих моментах, когда нужно откатить код на версию, написаную 3 часа назад - такое бывает сплошь и рядом.
Особенно это актуально для той самой топик-ветки - ведь не всегда получается сделать фичу работающей сразу и без ошибок.
> Значит ли это, что мне надо "терпеть" и копить изменения, чтобы потом всё закоммитить одним движением?
ОтветитьУдалитьЯ думаю вот что имеется ввиду - при работе над задачей разработчик несколько раз делает коммит в ветку, но в результате ветка задачи вливается в интеграционную ветку и после этого удаляется.
Т.е. вот эта серия промежуточных коммитов - временный артефакт, в дальнейшую работу пойдет одиночный коммит - результат слияния.
> ветка задачи вливается в интеграционную ветку и после этого удаляется.
ОтветитьУдалитьПлохая практика. Если всплывет ошибка через неделю или две и надо будет искать концы - не найдешь. У меня бывали случаи, когда надо было искать источник дельты спустя месяц (!) - и тут вся сохраненная на ветках история очень пригождалась.
> в дальнейшую работу пойдет одиночный коммит - результат слияния
Ну это понятно. Но, тем не менее, вся история важна. А то, что место занимает - так сейчас место на HDD стоит дешевле воды :)
Aquary комментирует...
ОтветитьУдалить>Плохая практика. Если всплывет ошибка через неделю или две и надо будет искать концы - не найдешь.
Ну, коммит в trunk останется, в нем перечислены измененные файлы и есть ссылка на оригинальную задачу в трекере. Какая еще нужна информация ?
В принципе, оригинальную ветку можно и не удалять. Их тогда именовать как, интересно, чтобы было и уникально и информативно ? Ведь это ж будут сотни и тысячи веток.
С другой стороны, удаление ветки после вливания в trunk служит надежным маячком, что ветка влита :) Т.е. если есть ветка это значит, над ней ведется работа.
> Какая еще нужна информация ?
ОтветитьУдалитьНа транке остается *результат мёржа* дельты разработчика и тоо, тчо было на транке.
При этом *дельта разработчика* - становится неизвестной.
То есть нельзя будет с уверенностью сказать - ошибка в коде появилась в результате ошибки слияния или ошибки разработчика.
Конечно, зачастую всё на потом поставлено и быстрее поправить ошибку, чем искать её причину. Однако - такие ситуации возможны.
> Их тогда именовать как, интересно, чтобы было и уникально и информативно ?
Например, схема
___
покрывает собой бОльшую часть ситуаций. Здесь branch type может быть ввведен, чтобы показать, что ветка - интеграционная, отладочная, для работы над задачей и т.п. task_id в случае интеграции может быть пропущен. В общем, соглашение об именовании веток и меток - оно в любом случае полезно.
Хы... форматирование обрезало имя бранча :))
ОтветитьУдалитьПопробую по-другому
[branch_type]_[developer_id]_[task_id]_[comment]
>На транке остается *результат мёржа* дельты разработчика и тоо, тчо было на транке.
ОтветитьУдалитьПри этом *дельта разработчика* - становится неизвестной.
Я тут посмотрел, как будет в меркуриале - в trunk после слияния получается вся история коммитов разработчика + интеграционный коммит.
Но там и ветку толком удалить нельзя, только "закрыть", т.е. проставить определенный флажок.
В subversion все вроде гораздо печальнее.
Почему они слияние-то не могут сделать, интересно, это архитектурные ограничения какие-то ?
> Почему они слияние-то не могут сделать, интересно, это архитектурные ограничения какие-то ?
ОтветитьУдалитьКак не могут? В СВН есть слияние, что бы там ни говорили. Сам пользуюсь :) Да, где-то оно сделано лучше, однако - в СВН оно вполне себе есть. :)
Ну, понятно, слияние есть, я тоже пользуюсь :) но по сравнению с другими системами, та же Plastic SCM :) функциональность крайне хромает.
ОтветитьУдалитьЗаметь - все плачут, колются, "но продолжают жрать кактус" :)
ОтветитьУдалитьЦена перехода на другую систему довольно высока, вот и потребляем кактус.
ОтветитьУдалитьК тому же, у subversion есть плюсики типа хранения нескольких проектов в одном репо и система безопасности. К примеру, можно запретить модифицировать trunk "кому попало".
В общем, кушаем, что есть.
ОтветитьУдалить