Основы использования бранчинга для параллельной разработки

Вступление

Как справедливо заметил Fred Brooks, серебряной пули, способной поразить зверя разработки программного обеспечения, не существует. Пока возникают новые требования, идеи и находятся новые баги, программы живут и изменяются. Путь, который проходит код от версии к версии, может быть крайне сложен и извилист. К его созданию причастно много людей: разработчики, тестировщики, бизнес-аналитики, заказчики и т.п. Несмотря на то, что существует много разных видов разработки – аутсорсинг, продуктовая разработка, open-source и т.п., проблемы, стоящие перед командой, остаются примерно одинаковыми. Программное обеспечение – вещь сложная, потребитель хочет получить его как можно быстрее (и дешевле). Качество при этом должно быть приемлемым. Перед командой разработки стоит серьезная задача – наладить эффективное взаимодействие. Одним из самых главных средств коллаборации внутри команды разработчиков является сам код, который они пишут.

В данный момент на рынке получают широкое распространение распределенные системы управления версиями – DVCS. Однако, львиную долю рынка удерживают традиционные и более простые в использовании централизованные системы, такие, как, например, SVN. Система управления версиями, а вернее, ее грамотное использование, играет ключевую роль в обеспечении эффективного взаимодействия. Вспомните, как давно вы читали книгу про свою VCS? Команде, в которой нет людей, способных выстроить грамотное взаимодействие через VCS, исходя из потребностей проекта, не позавидуешь.

Управление релизами

Давайте представим себе идеальное управление релизами. Релиз-менеджер может оценить состояние кода и выбрать реализованный функционал для включения в релиз. Этот функционал должен быть готов и протестирован. Также релиз-менеджер может включить исправления дефектов с прошлого релиза. Неготовый, нестабильный и непротестированный функционал в релиз попасть не должен. Если от QA-специалистов поступает информация о нестабильности того или иного функционала, релиз-менеджер должен иметь возможность убрать его из релиза. Часто возникает потребность в переносе исправлений дефектов на уже работающую у конечного пользователя версию, потому что он по каким-то причинам не может перейти на новую.

Если немного сменить точку зрения и посмотреть на процесс работы над кодом со стороны разработчика, то он должен сидеть в своей песочнице и не подвергаться влиянию дестабилизирующих коммитов со стороны коллег. В идеале, разработчики должны обмениваться только законченными и стабильными наборами изменений. Так ведь проще понять что было сделано, правда? Тем не менее, коммиты не должны диктовать разработчику стиль его работы, и он всегда должен иметь возможность вкомитить только частично выполненный функционал.
Описанные выше проблемы имеют несколько решений. Одно из них – правильный выбор и грамотное использование проектной системы управления версиями. Еще одно – понимание возможных стратегий бранчинга (ветвления) и цены, которую придется заплатить за всю эту роскошь.

Использование бранчинга позволяет нам убить двух зайцев одним махом: выполнять стабилизацию релизной версии (процесс более известный как багфиксинг) и одновременно осуществлять расширение приложения новым функционалом для следующего релиза. Это два основных, хотя и не единственных, способа использования бранчинга на проекте.

Отступление про версионность кода

Как правило, системы управления версиями хранят историю изменений в виде линии (централизованные) или графа (распределенные). Ветка (бранч) – это просто линия разработки кода, которая имеет общую историю с другими ветками и существует параллельно с ними. Jeff Atwood в своем блоге сравнивает ветки с параллельными вселенными. В такой вселенной в какой-то момент история пошла по-другому относительно других. Это дает нам безграничные возможности, которые уравновешиваются безграничной сложностью наших вселенных.

Как правило, одна из наших историй является основной и носит гордое имя trunk или mainline. По аналогии с деревом, от нее отходят другие ветки. В эту ветку рано или поздно попадает готовый (или не совсем) функционал и исправления ошибок.

Branch per release

Рассмотрим первый из этих случаев, когда отдельная ветка создается под каждый релиз. Это делается для того, чтобы исправлять дефекты, найденные после выпуска релиза или во время его тестирования. Этот процесс обычно называется стабилизацией. При этом сами исправления (багфиксы) не остаются только в релизных ветках, а переносятся в mainline (если история релиза и mainline не слишком разошлись), делая ее стабильнее. Код в релизной ветке изолирован от дестабилизирующего влияния разработки нового функционала и при этом не блокирует ее. Сама по себе релизная ветка предоставляет легкую возможность осуществлять поддержку релизной версии. Когда прекращается поддержка релиза, его ветка замораживается. А пока идет проект, mainline продолжает свое развитие, являясь точкой, в которой накапливается новый функционал для следующих релизов.

Таким же образом можно осуществлять поддержку релизов для разных заказчиков, выделяя по ветке для каждого, если по каким-то причинам им нельзя поставить одну и ту же версию. Хочу отметить, что поддержка разных вариаций одной и той же версии — задача трудоемкая и ее следует избегать по мере возможности.



Branch per feature

Следующий случай — это выделение отдельной ветки для разработки нового функционала. Как правило, это одна логически законченная функциональная область, или просто feature. Новый функционал объединяется с основной веткой только после полного завершения, что позволяет избежать негативного влияния незавершенной работы на другие линии разработки. После того как новый функционал готов и объединен с основной веткой, другие ветки разработки должны быть интегрированы с mainline, чтобы не накапливался эффект отложенной интеграции. Использование веток для релизов и разработки позволяет нам не ждать, пока окончится тестирование и стабилизация релиза, а сразу приступить к разработке функционала для следующего.



Также можно создавать sub-branches для релизных и девелоперских веток, если нужны еще уровни изоляции. Во всех случаях создания новой ветки следует понимать цену ее поддержки, о чем будет упомянуто немного позже.

Интеграция между ветками

Основная ветка (mainline, trunk) является главным местом интеграции при помощи кода. Так или иначе, все изменения, сделанные разработчиками, попадают сюда. Тем не менее, она не должна превращаться в свалку нестабильного и незаконченного кода. Именно поэтому разработку новых фич рекомендуется проводить в отдельной ветке, интегрировать с основной, тестировать и только потом объединять изменения. Иными словами, mainline должна содержать достаточно законченный код, который может послужить основой для стабилизационной релизной ветки. Также, багфиксы из релизных веток, пройдя через mainline, попадают в ветки для разработки, таким образом, работа ведется над более стабильным кодом. Хорошим правилом является то, что мы не должны отдавать нестабильные изменения в другие ветки и что мы должны принимать стабильные изменения из других веток.



Рассмотрим ситуацию, отображенную на картинке:

  • В какой то момент в Mainline накопилось достаточное количество законченного функционала для выпуска Release 1.x. Для него была создана ветка, и после тестирования и стабилизации релиз ушел заказчикам.
  • Параллельно с этим стартовала разработка нового функционала:feature A и feature B, – каждая на своей ветке.
  • Баги, найденные закзачиками в Release 1.0, были исправлены на релизной ветке, и был выпущен Release 1.1. Багфиксы из него были объединены с Mainline, откуда попали в ветки для feature A и feature B. Таким образом, работа велась над более стабильным кодом.
  • Один из заказчиков по своим причинам не смог перейти на версию 1.1 и столкнулся с рядом специфичных для себя дефектов. Это было исправлено на специально сделанной для него ветке – Release 1.0.x.
  • Была закончена разработка feature A, и, после интеграции и тестирования, эти законченные изменения попали в Mainline. Ветка для feature B получает эти изменения сразу после их попадания в Mainline, чтобы работа велась над максимально актуальной версией кода.
  • Принимается решение о выпуске нового Release 2.x, включающего feature A, и для него создается ветка, на которой осуществляется сервис этого релиза, – 2.1, 2.2. Причем, багфиксы для релизной версии 2.2 не объединяются с Mainline, так как истории этих линий разработки кода уже слишком разошлись.


При оценке плюсов и минусов такого подхода, следует принимать во внимание:
  • Feature branches не стоят на пути Continuous Integration
  • Семантические конфликты не являются специфичными исключительно для бранчинга
  • Feature toggling и Branch-by-abstraction имеют ряд своих недостатков по сравнению с Feature branches.


Интеграция через Mainline не является единственным способом интегрироваться – возможна интеграция напрямую между ветками. Martin Fowler называет такой способ Promiscuous Integration. Для такого метода интеграции очень важна коммуникация внутри проектной команды.

Стабильность веток

У такой модели есть градация стабильности, где самыми стабильными являются релизные ветки, менее стабильной является mainline, и самыми нестабильными являются ветки для разработки. Как правило, на диаграммах самые стабильные ветки отображаются выше всех, а нестабильные – ниже всех.



Накладные расходы, связанные с использованием бранчинга

С бранчингом связаны следующие издержки:

  • Механические – это те действия, которые нужно совершить, чтобы создать ветку, переключиться с ветки на ветку, объединить (merge) изменения и т.п. Как правило, такие действия трудоемки для централизованных систем и относительно просты для децентрализованных.
  • Интеллектуальные – это те усилия, которые приходится приложить, чтобы держать в голове все существующие ветки и их предназначение. Как правило, существуют инструменты, которые облегчают эту задачу. Сюда можно отнести кривую обучения для сотрудников, связанную с освоением системы управления версиями.
  • Цена за тестирование – использование параллельной разработки способно серьезно увеличить цену ручного тестирования. Отложенное тестирование позволяет сократить расходы, но при этом имеет ряд своих недостатков. Любое автоматическое тестирование значительно уменьшает цену тестирования при использовании бранчинга. В целом, этот пункт зависит от стратегии тестирования, принятой на проекте.


Типы зависимостей между ветками и способы их решения

Между ветками могут возникать следующие зависимости:

  • Архитектурные – если мы меняем архитектуру на одной ветке, другие ветки могут зависеть от этих изменений.
  • Функциональные – некоторая новая функциональность не может быть закончена или не имеет особой ценности, пока не будет закончен другой функционал, от которого она зависит.
  • Зависимости от исправления дефектов – в случае исправления дефекта на одной ветке, может существовать несколько веток, которые должны получить это изменение.


Существует несколько типовых решений для работы с таким зависимостями:

  • Саб-бранчинг – зависимая функциональность реализуется в отдельном саб-бранче и потом объединяется со всеми заинтересованными ветками.
  • Остановка – разработка на ветке замораживается, пока не будет готова нужная функциональность.
  • Архитектурная абстракция – путем абстракции в системе создаются границы, которые изолируют разные части функциональности. В этом случае проблема решается не только на уровне системы управления версиями, но и на уровне дизайна приложения.
  • Использование заглушек – в системе используются fakes/stubs, которые заменяются на реальный функционал по мере его готовности.
  • Релиз, патч, ре-релиз – система выпускается в не полностью готовом виде и патчами доводится до совершенства (эту практику в некоторых отраслях принято называть платным бета-тестированием).


Заключение

Важно понимать, что грамотный модульный дизайн приложения может сильно уменьшить или свести на нет необходимость использования бранчинга и является мощным инструментом для решения проблем, связанных с параллельной разработкой.
Бранчинг позволяет нам одновременно вести два вида разработки: стабилизацию и реализацию нового функционала. Однако, это не единственный способ его применения. Например, отдельные ветки могут выделяться для разделения итераций или для изоляции разных команд.
Правильный выбор стратегии бранчинга зависит от потребностей проекта и возможностей/ограничений используемой системы управления версиями (которую, впрочем, никто не запрещает сменить). Ограничения реального мира, которые накладываются на процесс, часто невозможно решить без возможности осуществления паралелльной разработки. Тем не менее, неграмотное понимание и использование бранчинга часто приводит к анти-паттернам, которые и завершают этот материал.

Анти-паттерны бранчинга:

  • Merge Paranoia – разработчики боятся объединять код, поэтому накапливается негативный эффект отложенной интеграции.
  • Merge Mania – разработчики больше времени тратят на объединение изменений, чем на разработку.
  • Big Bang Merge – ветки не обмениваются законченными изменениями, поэтому происходит одно гигантское объединение в конце.
  • Never-Ending Merge – объединение никогда не останавливается, так как всегда есть что объединять.
  • Wrong Way Merge – объединение более поздней ветки разработки с более ранней версией.
  • Branch Mania – создание большого количества веток без нужной на то причины.
  • Cascading Branches – создание веток без объединения их с mainline в конце разработки.
  • Mysterious Branches – создание ветки без причины.
  • Теmporary Branches – создание ветки с изменяющейся причиной ее существования: ветка становится временным рабочим пространством.
  • Volatile Branches – старт ветки в нестабильном состоянии или перенос нестабильных изменений в другие ветки.
  • Development Freeze – остановка всей разработки для создания веток, объединения или создания релизов.
  • Berlin Wall – использование веток для разделения людей в команде, вместо разделения областей, над которыми они работают.
Share post
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 72

    –2
    Скажите честно, вы Continuous Delivery читали?
      0
      Это не основано на Continuous Delivery, скоре на материалах по разным VCS и по СI. Итеративный процессе в agile команде будет основан на CI / использовании бранчей / автоматическом тестировании / автоматическом развертывании, так что сам принцип Continuous Delivery не несет в себе ничего нового.
        –1
        Так я еще раз спрошу: вы Continuous Delivery читали?
          0
          Книгу? — нет, не читал.
            –10
            Понятно.

            Вы что предпочтете — чтобы я тут кратко пересказал аргументы против бранчей, или прочитать их в книжке?
              0
              Аргументы против приводите, книгу занесу в to-read для себя.
                –1
                Аргументы против бранчинга просты: оверхед на мерж во-первых, и отсутствие гарантии работоспособности mainline (после мержа) во-вторых. Разработка на мейнлайне (в сочетании с еще несколькими приемами) обе эти проблемы решает.

                Естественно, мы сравниваем варианты «бранчинг с CI и полным покрытием» и «CD с полным покрытием», без полного покрытия говорить тут не о чем.

                Проще говоря, бранчи жизнеспособны только тогда, когда у вас есть административный ресурс, заставляющий всех мержиться не реже раза в день.
                  +2
                  > и отсутствие гарантии работоспособности mainline (после мержа)

                  А кто даёт гарантии работоспособности мейнлайна в случае разработки исключительно в мейнлайне?
                    –1
                    Автоматическое тестирование.

                    Просто когда у вас коммиты в мейнлайн идут часто, то починка проблемы путем отката последнего коммита лишает нас очень маленького куска функциональности (плюс, проблема очень легко локализуется). А бранчи (которые ведут к редким коммитам в мейнлайн) банально умножают время.
                      +2
                      Автоматические тесты можно запустить и после мерджа. И пофиксить все упавшие тесты.

                      Просто когда у вас коммиты в мейнлайн идут часто, то починка проблемы путем отката последнего коммита лишает нас очень маленького куска функциональности (плюс, проблема очень легко локализуется). А бранчи (которые ведут к редким коммитам в мейнлайн) банально умножают время.


                      Напомню: в вашем комментарии вы написали об «отсутствии гарантий», а не увеличении стоимости поддержки этих «гарантий».

                      Стало быть, никакого «отсутствия гарантий» нет?
                        +1
                        Автоматические тесты можно запустить и после мерджа. И пофиксить все упавшие тесты.

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

                        Стало быть, никакого «отсутствия гарантий» нет?

                        Если быть совсем точным, не «никакого отсутствия гарантий нет», а «эта проблема не является специфичной для бранчей».
                          +1
                          Да, это в среднем дороже. И это расплата за «стабильный мейнлайн».

                          Если быть совсем точным

                          Именно. Из вашего пессимистичного комментария остался лишь аргумент «мерджить сложнее», о котором и так все знали :-)

                          Вопрос: к чему было разводить пафос на тему чтения книги?

                          ps: книгу я читал ;-P
                            –1
                            Да, это в среднем дороже. И это расплата за «стабильный мейнлайн».

                            Мейнлайн стабилен в любом случае.
                              +2
                              Мейнлайн стабилен в любом случае.

                              Не совсем. У вас нет песочницы для экспериментов и временного кода.

                              Плюс в идеологии с фичабранчами вы получаете более простой способ управления фичами — когда какую релизить, и релизить ли вообще.

                              Но так или иначе — ветка себя исчерпала, продолжения я у неё не вижу (и вообще пошёл спать :-) )
                                –5
                                Не совсем. У вас нет песочницы для экспериментов и временного кода.

                                Есть. Локальный компьютер.

                                Плюс в идеологии с фичабранчами вы получаете более простой способ управления фичами — когда какую релизить, и релизить ли вообще.

                                Feature Toogle.
                        +2
                        1. Никто не запрещает синхронизировать ветки с mainline, как только в mainline попадают законченные изменения. Перед мержем с mainline никто не запрещает сначала синхронизироваться с оной и прогнать тесты.

                        2. Любой существенный функционал или рефакторинг не выполнишь за день, частые коммиты таких работ в mainline дестабилизирует его на срок до окончания разработки этого функционала или окончания рефакторинга. Откат последнего коммита в середине работы может привести к тому, что в mainline будет полуготовый функционал, что негативно сказывается на стабильности mainline.

                        3. Никто не запрещает интегрироваться между ветками, чтобы не накапливался эффект отложенной интеграции, если этот эффект способен вызвать big bang merge.

                        4. Использование веток позволяет осуществлять параллельную разработку, что позволяет, заплатив определенную цену, обойти ограничения реального мира — например одновременную пост-релиз поддержку и добавление новых фич.

                        5. Еще раз повторю что обмениваться лучше законченными изменениями но при этом коммитить часто — при работе mainline-only это проблематично.
                          0
                          Никто не запрещает синхронизировать ветки с mainline, как только в mainline попадают законченные изменения. Перед мержем с mainline никто не запрещает сначала синхронизироваться с оной и прогнать тесты.

                          Никто не запрещает интегрироваться между ветками, чтобы не накапливался эффект отложенной интеграции, если этот эффект способен вызвать big bang merge.

                          Никто не мешает, но очень мало кто делает. Собственно, я об этом и говорю — административный ресурс.

                          Любой существенный функционал или рефакторинг не выполнишь за день, частые коммиты таких работ в mainline дестабилизирует его на срок до окончания разработки этого функционала или окончания рефакторинга.

                          Еще раз повторю что обмениваться лучше законченными изменениями но при этом коммитить часто — при работе mainline-only это проблематично.

                          Маленькие шаги и feature hiding.

                          Использование веток позволяет осуществлять параллельную разработку, что позволяет, заплатив определенную цену, обойти ограничения реального мира — например одновременную пост-релиз поддержку и добавление новых фич.

                          Работа на мейнлайне это тоже позволяет.
                          0
                          Коммиты в главную ветку обычно запрещены, разрешены только прямая интеграция (создание веток релизов) и обратная интеграция (слияние веток разработки с главной веткой после окончания цикла разработки).

                          Главная ветка используется командой QA для непрерывного тестирования и всегда стабильна. Обратная интеграция из веток с релизами возможна только для горячих обновлений — это исправление критических багов прямо на ветке релиза с последующим слиянием ветки обратно с главной.
                            0
                            К сожалению, в такой ситуации фраза «всегда стабильна» — это самообман.
                              0
                              Это не самообман. Стабильным считается состояние когда программа не содержит багов, которые ранее возникали. Мы же, программисты, знаем что баги есть всегда, просто тестировщик или пользователь не нашел условий для их обнаружения. Поэтому если Вы построили тесты, которые были написаны по мотивам найденных ранее багов пользователями или тестировщиками, то когда тесты будут успешно пройдены это даст Вам возможность говорить: «продукт стабильно работает»
                                0
                                Стабильным считается состояние когда программа не содержит багов, которые ранее возникали.

                                Это откуда такое определение?

                                (исходя из него нетестированная программа — стабильна)

                                Поэтому если Вы построили тесты, которые были написаны по мотивам найденных ранее багов пользователями или тестировщиками, то когда тесты будут успешно пройдены это даст Вам возможность говорить: «продукт стабильно работает»

                                И вы считаете, что мейнлайн (в который разрешено интегрироваться только после окончания разработки) будет всегда успешно проходить эти тесты?
                                  0
                                  >>Это откуда такое определение?
                                  Тестированием на работе занимаюсь. Поэтому интересоваться «стабильностью» мне по штату положено.

                                  >>будет всегда успешно проходить эти тесты?
                                  К этому надо стремиться и тесты как раз и пишутся для того чтобы получить ответ «Насколько стабилен транк?».

                                  Транк должен находиться в таком состоянии, чтобы в любой момент из него можно было собрать билд для выдачи обновленного продукта. Он может быть развален только при merge с какой-либо фичей или багфиксом.

                                  На практике бывает все куда сложнее, но и там стараются придерживаться того что стабильная ветка это для пользователей, а не разработчиков. Пример из мира OpenSource проект FreeBSD:

                                  current — это тип ветки для разработчиков. Если в эту ветку суются «среднячки» то на форумах появляется очень много «После обновления до… перестало....».

                                  releng_9, releng_8 — это стабильные ветки. Это промежуточное решение между «самым последним словом технической мысли» и «самое стабильное на данный момент». В стабильные вносятся комиты только тогда, когда они обкатаны в current-ветке и код для мержа просмотрен не одним разработчиком и баги маловероятны, хоть и возможны.

                                  releng_9_0, releng_9_1 и др. — это релизные ветки. В них вносятся комиты только с уровнем blocker, critical и security.
                                    0
                                    Тестированием на работе занимаюсь. Поэтому интересоваться «стабильностью» мне по штату положено.

                                    Тем не менее, откуда именно такое определение?

                                    Он может быть развален только при merge с какой-либо фичей или багфиксом.

                                    Вот об этом моменте и речь. У вас сразу после мержа (коммита) проходят все тесты? Всегда?
                                      0
                                      >>Тем не менее, откуда именно такое определение?
                                      Этот термин в голове сам появляется после года тестирования. Рекомендую почитать книгу Коннера про тестирование

                                      >>У вас сразу после мержа (коммита) проходят все тесты?

                                      А какую Вы решаете задачу? Вам же главное положить в «центральное место исходников» такое, чтобы все было хорошо. Так? Вот и делайте 'hg push' в это место, только тогда, когда станет зеленым! Поясню мысль на примере использования Mercurial:

                                      1) клонируем репозитарий hg clone
                                      2) hg pulll vasya-feature-repositary-url.. Забираем новые комиты от Васи
                                      3) hg up default -> hg merge vasya-feature -> hg ci -m «merge with vasya-feature». Мержим комиты Васи с тем что у нас в папке после п.1
                                      4) Тестируем, если что-то красное сообщаем Васе
                                      5) hg pull vasya-feature-repositary-url. Забираем новые комиты после фиксов от Васи
                                      6) Повторяем п. 2 — п. 5 столько раз пока не станет зеленым

                                      п.2 и п.6 повторяем с любым другим разработчиком

                                      Работая с Меркуриал Вы работаете со своей локальной папкой! Мержите только в нее, комитите тоже только в нее, даже когда сети нет.

                                      А когда вы решили что default стал «зеленым», только тогда:

                                      hg push general-default-repositary-url

                                      Основное допущение: general-default-repositary-url это репозитарий для «скачивания» всеми, но заливать должны только «тестировщики» или ответственные за фичу, которые смогут гаррантировать что их мержи не развалят, которые все что нужно сделали на своих локальных машинах или отдали URL-ы на репозитарии со своих машин, чтобы тестировщики их забрали и протестировали.
                                        0
                                        Этот термин в голове сам появляется после года тестирования. Рекомендую почитать книгу Коннера про тестирование

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

                                        Основное допущение: general-default-repositary-url это репозитарий для «скачивания» всеми, но заливать должны только «тестировщики» или ответственные за фичу, которые смогут гаррантировать что их мержи не развалят, которые все что нужно сделали на своих локальных машинах или отдали URL-ы на репозитарии со своих машин, чтобы тестировщики их забрали и протестировали.

                                        Это допущение невыполнимо.

                                        Понимаете ли, в чем дело. Рано или поздно в транке все равно будет мерж, который нужно будет тестировать. Чем сложнее проект, тем чаще это будет происходить. И никакое тестирование на локальной машине не поможет, потому что за время этого тестирования (а оно долгое, потому что тестируется весь код) в транк положили что-то еще, и по факту все равно будет новый мерж.
                                          0
                                          >>термин «стабильный»
                                          Он один на всех! Он не может быть понятым по разному, а если понимается по разному значит команда о чем-то внутри себя не до конца договорилась.

                                          Напишите, пожалуйста, по-подробнее о том как этот термин, стабильность, может иметь другое значение для тестировщика и разработчика или руководителя проектов?! Очень интересно.

                                          >>Понимаете ли, в чем дело. Рано или поздно в транке все равно будет мерж, который нужно будет тестировать.
                                          Ваш страх комита и мержа основан на том что он лежит «сверху» и его тут же после комита может взять и забрать себе любой из разработчиков. Вы вероятно используете рудиментарную SVN и пора бы уже пробовать новые способы работы к примеру Git или Mercurial

                                          Еще раз, страх этого «проблемного комита или мержа» пропадает, только тогда, когда после него есть другие комиты, которые фиксят проблемный комит или мерж.

                                          Выше я уже написал о том как именно сделать так, чтобы всем стало доступным состояние исходников которое по прежнему «зеленое».
                                          Вам всего лишь нужно положить в центральный репозитарий с исходниками «новая фича возможно с багами » + «набор комитов которые фиксят баги, которые нашлись в результате тестов». Все! На верху будет та ревизия кода, которая проходит тесты.

                                          Попытаюсь пояснить мысль еще раз:
                                          1) Путем hg clone вы работаете со своей рабочей Локальной на вашем ноутбуке папке!
                                          2) С вашего Ноутбука в центральный репозитарий все изменения попадут только после того как вы сделаете hg push. ( Но вы можете его не делать до тех пор пока не приведете в состояние когда проходят тесты)
                                          3) Возможно вы не знаете, но Git, Mercurial делают комиты не в центральный «в сети» сервер исходников, а в локальную на Вашем ноутбуке папку.
                                          4) Ваши комиты, никак, никаким образом, никакой магией не попадут в центральный репозитарий до тех пор, пока вы не сделаете «hg push»
                                            0
                                            Напишите, пожалуйста, по-подробнее о том как этот термин, стабильность, может иметь другое значение для тестировщика и разработчика или руководителя проектов?!

                                            Я хотел сказать, что есть команды, в которых это слово имеет другое значение.

                                            Все! На верху будет та ревизия кода, которая проходит тесты.

                                            … и не включает изменения соседних разработчиков, которые забыли смержить.

                                            Попытаюсь пояснить мысль еще раз:

                                            Спасибо, я в курсе, как работает DVCS. К сожалению проблемы «очень большой проект, который нельзя протестировать на ноутбуке» они не решаеют.

                                            Ваши комиты, никак, никаким образом, никакой магией не попадут в центральный репозитарий до тех пор, пока вы не сделаете «hg push»

                                            Вот только после того, как я сделаю hg push случится одно из двух: либо в центральном репозитории будет мерж с изменениями других разработчиков (следовательно, возможные ошибки), либо мой коммит не будет включать изменения других разработчиков (=они пропадут).
                            0
                            Скажите, а как вы с одним мэйнлайном, без бранчей, делаете CD для двух разных клиентов?
                              0
                              Поясните свой вопрос, пожалуйста. Вы имеете в виду, что для двух клиентов зачем-то нужно выкатывать разные версии кода?
                                0
                                Да, именно так. Для двух клиентов надо выкадывать не сильно, но различающиеся версии.
                                  0
                                  Ну, если вкратце, есть два решения:

                                  (а) выделяем общий код отдельно (как инфраструктуру), он живет на своем мейнлайне, код клиентов по отношению к нему находится downstream
                                  (б) делаем два бранча и плачем о стоимости интеграции

                                  Впрочем, «две несильно различающиеся версии» — это всегда «плачем о стоимости интеграции».
                                    0
                                    Что значит «плачем о стоимости интеграции»? Почему вы думаете, что эта интеграция
                                    а) будет дорогой
                                    б) вообще нужна
                                      0
                                      Если она (интеграция) не нужна, то не нужны и бранчи.

                                      А дорогой она будет ровно потому, что «мелкие изменения» (если они не локализованы в модуль) расползаются по всему проекту, и, как следствие, имеют непредсказуемый импакт (то есть привет сквозному ретесту).

                                      А если можно локализовать изменения для клиента в модуль (как мы пытаемся делать), то все становится проще, и никаких бранчей уже не требует.
                                        0
                                        Ну вот пример, котрый вы просили.
                                        Вам нужно релизить два продукта, имеющих один codebase, но различающиеся в маленькой части. Как вы будете делать это без бранчей?
                                          0
                                          Я тоже только что ответил на этот вопрос: по возможности я постараюсь избежать бранчей, изолировав эту маленькую часть в отдельный компонент. Это решение обычно лучше и с архитектурной точки зрения.

                                          Если мне это не удастся — я буду делать бранчи, но стараться рассматривать их как даунстрим.
                                            0
                                            А как вы будете контролировать совместимость этих отдельных компонент и основного продукта? Версионировать их будете отдельно или вместе?
                                            А ещё у вас 10 клиентов, из которых 8 обновляются, а два — не обновляются, потому что у них такая политика. И как вы будете делать багфиксы для тех двух оставшихся клинетов, один из которых брендирован, а второй приносит 50% прибыли?
                                              0
                                              А как вы будете контролировать совместимость этих отдельных компонент и основного продукта? Версионировать их будете отдельно или вместе?

                                              Эти решения не отличаются между бранчами и компонентами.

                                              А ещё у вас 10 клиентов, из которых 8 обновляются, а два — не обновляются, потому что у них такая политика.

                                              Не обновляются — не получают багфиксов. Тут же все просто.
                                  0
                                  Вы реально этого не понимаете? О каких «крупных проектах» вы говорили в своих других комментариях?

                                  Пример:
                                  Команда выпустила продукт версии 1.0 и там есть супер фича №1. В магазин пришел покупатель и купил эту версию продукта. Прошло время и работа команды продвинулась так далеко вперед и сделали фичу №2, фичу №3 и др. фичи. Другими словами они выпустили версию продукта 2.0.

                                  Вдруг, внезапно, неожиданно: покупатель, тот самый, что купил версию 1.0 и купил ровно из-за фичи №1, вдруг находит багу в этой фиче №1.

                                  Что делать с таким покупателем?

                                  Варианты:
                                  1) Предложить купить версию 2.0, в которой эта бага не повторяется? На что он может справедливо ответить: «Так мне 1.0 достаточно, а новые фичи мне не нужны!».
                                  2) Выслать версию 2.0 бесплатно. Как вариант, но это себе в убыток, но так делают и это достаточно распространенная практика
                                  3) Откатиться на состояние исходников по версии 1.0 и поправить багу, выпустить обновленный 1.0.1, выслать это покупателю.

                                  есть и др. варианты, но эти более распространены. Но п.3, который достаточно распространен вынуждает производителя выдавать несколько билдов.

                                    +1
                                    Да достаточно слова «брендинг». Выпустили вы для партнера брендированную версию: все то же самое, но картинки другие.
                                      0
                                      Для брендинга надо использовать соответствующие механизмы, заложенные в решение (конфигурацию, темы, что-то еще), а не бранчи.
                                      0
                                      Вы сейчас говорите о продукте (коробке). Для продуктов CD применим хуже (хотя и все равно применим). Я же говорил о заказной разработке, где, по факту, нет понятия «версия».

                                      Ну и да, надо понимать, что мало «откатиться на состояние исходников». По факту нужно полностью поднять ландшафт под 1.0, с полным ретестом. Так что тут бранчи уже сами по себе мало значат.

                                      И да, branch-per-release CD не противоречит никак, потому что критичные баги фиксятся в релизных бранчах и немедленно прокидываются в мейнлайн.
                                        0
                                        Я уже написал ниже, что вы почему-то спорите о деталях, не различая главного — жизненного цикла продукта. И делаете это очень воинственно.
                                        Это как говорить, что утюг лучше стиральной машины, аргументируя тем, что после стиралки вещи мятые.
                                        Но вообще спасибо за этот спор — по дороге на работу пришла идея статьи на эту тему. Напишу до весны.
                                          0
                                          Я как раз хорошо представляю себе жизненный цикл продукта (хотя, несомненно, жизненный цикл решения я себе представляю лучше).

                                          (чистый) CD все-таки лучше всего подходит для сервисов и решений, и только потом — для продуктов. Но его идеология «интегрируйтесь как можно чаще» часто показывает себя выгодной.
                                            0
                                            Я как раз хорошо представляю себе жизненный цикл продукта

                                            и не смотря на это вы написали совершеннейшую ерунду выше.
                                              0
                                              Я буду рад услышать, что именно в моих суждениях кажется вам ерундой.
                              +1
                              Проще говоря, бранчи жизнеспособны только тогда, когда у вас есть административный ресурс, заставляющий всех мержиться не реже раза в день.


                              Это сложный вопрос, но мне кажется что примеры разработки open-source проектов говорят нам об обратном. Можно далеко не ходить и рассмотреть то, как появился Git и какая модель используется для разработки Linux.
                                –3
                                Это сложный вопрос, но мне кажется что примеры разработки open-source проектов говорят нам об обратном. Можно далеко не ходить и рассмотреть то, как появился Git и какая модель используется для разработки Linux.

                                Я сужу с позиции разработки конкретных заказных проектов со сроками. Там, к сожалению, опыт open-source не очень веселит.
                                +1
                                Ваш спор бессмысленный, т.к. и бранчинг, и CD хороши по своему. Вопрос лишь в масштабируемости.

                                Предложенный Вами способ хорош для маленьких проектов на несколько человек. Там действительно не нужен оверхед на регулярный мердж. Но вот с масштабированием у этого способа не очень. Если разрабатывать что-то типа ядра Linux, то без бранчинга никуда. Просто нужно понять, где та критическая величина проекта, после которой бранчинг будет уместен.
                                  0
                                  Просто нужно понять, где та критическая величина проекта, после которой бранчинг будет уместен.

                                  У вас нет ощущения, что после какой-то критической величины оверхед на мерж может быть выше, чем стоимость разработки? Я с таким сталкивался.
                                    0
                                    А какие альтернативы мерджу Вы можете предложить, когда имеется несколько параллельных релизных веток, и необходимо регулярно портировать между ними код багфиксов? Я пример Линукса привел не случайно, это наиболее показательный пример масштабного проекта.
                                      0
                                      Первый пункт: не делать параллельные релизные ветки. Для продуктов это, очевидно, сложно, но продуктов не так много, как можно было бы подумать.

                                      Если этого нельзя сделать, тогда без мержа вы не обойдетесь. Вопрос только в том, что, куда и в каких условиях вы будете мержить.
                    –6
                    О чем эта статья? Хотя наверно для начинающих кто еще слабо знаком с этим но уже использовал, будет полезно в качестве укрепления.
                      +3
                      Статья про основы использования бранчинга. Целью было описать базовое применение и познакомить с overhead'ом/зависимостями при активном использовании веток. Естественно, использовать нужно только то, что работает и вариантов эффективно применять ветвление намного больше.
                        0
                        Вот если бы тут было реально про оверхед то да. Оверхед это когда каждый день начинается с разрешения конфликтов после мержа. И тут нужны примеры, без примеров и чужого или своего опыта, понять какой оверхед это может принести невозможно.
                          +1
                          Семантические конфликты не являются специфичными исключительно для бранчинга и будут везде, где более одного разработчика работает над одним и тем же набором файлов. И например DVCS (Git, Mercurial, etc) хранят полную историю коммитов (в отличие от многих централизованных систем), что облегает процесс мержа.
                      0
                      Мое субьективное ощущение от представления
                      1) того сколько надо будет сидеть с merge tool чтобы поддерживать эту стратегию
                      2) того, сколько версий надо будет проверять QA (добавим к этому стоймость квалификации QA чтобы хорошо разбирались в ветках)
                      3) проблемность Continuous Integration
                      … довольно неприрятно. Мне кажется такой паттерн больше подходит для OpenSource проектов, где каждый берет свою ветку, разрабатывает функциональность и предлагает ее ответсвенному за коммиты, а стоимость QA более абстрактна. Тем более скорее CI там будет приоритетом ниже, чем в бизнес решении.
                      Но вообще мысль и статья интересная, спасибо.
                        +1
                        1. Я бы сказал, что это зависит от того, какой системой контроля версий исходного кода вы пользуетесь. В Perforce, конечно, будут проблемы, а вот в Git — всё довольно гладко проходит (почти всегда автоматичесуий мёрдж с минимальной работой программиста).
                        2. QA тестируют только главную ветку (master/HEAD/production)
                        3. Сборка CI идёт только для главной ветки (master/HEAD/production)
                          +1
                          По пунктам 1 и 2 упомянут механический и интеллектуальный overhead при использовании веток. Каждая новая ветка не бесплатна и добавляет сложность в процесс. Ветки позволяют обойти ограничение реального мира на то, что трудно одновременно стабилизировать и разрабатывать. Тем не менее количество веток должно быть сведено к необходимому минимуму именно по причинам накладных расходов на их поддержку.

                          По пункту 3 я не считаю что ветки являются препятствием для CI, это упомянуто. Впринципе для того чтобы собирать нужную ревизию необходимо просто обновить рабочую копию, на которой собирается билд на нее, все остальное одинаково для всех веток. Грамотный билд инжиниринг поможет решить этот вопрос. Насколько просто это реализовать зависит от используемой инфрастурктуры.
                          0
                          Про обмен только стабильными изменениями понравилось, но это требует определенной дисциплины от команды — каждый должен перепроверять, что его изменения действительно стабильны перед тем, как отдать их коллегам.

                          В зависимости между ветками забыли упамянуть рефакторинг. В реальных проектах он часто необходим и очень здорово усложняет мерж веток. Бороться с этим сложно. Можно отводить на рефакторинг отдельную фазу до разработки, но на практике заранее всего не угадаешь, что захочется переписать.

                          Вообще, даже кроме этого, мержить ветки практически всегда трудозатратно и лучшая практика тут, по моему опыту, сводить к минимуму время паралельной разработки, чтобы мержить все по горячим следам и минимум изменений. В идеале команда работает одновременно над одной фичей, с утра начинается работа над отдельными частями, вечером все мержится.
                            0
                            К сожалению реальный мир накладывает ограничения и не все можно успеть сделать за день) Если бы был телепорт не нужны были бы автомобили. А по поводу зависимости от рефакторинга — спасибо, я думаю можно отнести это как частный случай архитектурной зависимости.
                            –1
                            Коллеги, а давайте, если уж говорим по-русски, не использовать чудовищных слов типа «бранчинг», есть же нормальное слово «ветка» и не менее нормальное «ветвление», то же относится и к калькам фразеологизмов silver bullet, rocket science, etc.

                            По делу — в условиях скоростей веб-разработки классическая схема одна ветка на релиз, по-моему, не живет вообще, поскольку релизы, если под релизом понимать совокупность изменений, выкатываемую на продакшн, в вебе происходят иногда и больше раза в день, а заниматься по нескольку раз в день мержем веток не слишком продуктивно. Вариант «одна ветка для одного нового вида функциональности» хорошо живет для достаточно больших кусков функционала, для мелких допилов и багфиксов создавать ветки тоже смысла мало (разве что создавать раз в итерацию ветку только для бакфиксов, например). Интересно было бы почитать, какие схемы удобны с точки зрения минимизации количества времени, уходящего на работу с ветвлением.
                              0
                              Я бы посоветовал не забывать про функциональное строение команды, работающей над проектом, так как он — в идеале — имеет архитектуру с определенным стилем и чем лучше строение команды отвечает этому стилю, тем более производительным будет их труд. Это касается и числа конфликтов при слияниях.

                              К примеру, если речь идет о Web разработке и проект разрабатывается с использование MVC фреймворка, то желательно, чтобы был программист, который отвечал бы за слой Model и саму схему базы данных (в случае отсутствия DBA).
                                0
                                >>чтобы был программист, который отвечал бы за слой Model
                                А если этот человек уйдет в отпуск\уволится? Лучше всего не программиста, а чтобы «роль знающего фичу». А уж эту роль по переменно должны исполнять несколько человек, чтобы не исчезновение конкретного программера не коснулось команду!
                                  0
                                  Такой риск есть, но как говориться незаменимых людей не бывает. Другой программист сможет подхватить его работу спустя некоторое время. В любом случае эффект от разделения труда будет покрывать все возможные последствия ухода того или иного члена команды.
                                    0
                                    Это, простите, какой же эффект?
                                      0
                                      Извините, но я Вас не понимаю.

                                      В одной фразе:
                                      >>то желательно, чтобы был программист, который отвечал бы за слой Model и саму схему базы данных (в случае отсутствия DBA).
                                      Вы говорите, что нужно все в одного человека «всунуть».

                                      А в другой:
                                      >>В любом случае эффект от разделения труда будет покрывать все возможные последствия ухода того или иного члена команды.
                                      Тут Вы уже говорите, что разделение очень важно.

                                      Как все же Ваша точка зрения?
                                        0
                                        Я сторонник такого подхода, когда функциональное строение команды соотвествует архитектуре проекта над которым она работает. Такой подход будет предполагать взаимодействие между членам команды, аналогичное взаимодействию между функциональными частями в архитектуре проекта.

                                        Никто не говорил про «всовывать» все в одного человека. Как раз-таки наобарот, когда нет разделения труда отдельным разработчикам приходиться заниматься всем понемногу — это плохо.

                                        2 lair — эффект от разделения труда. Капитализм наглядно показал его преимущество.
                                          0
                                          Простите, у вас есть достоверное сравнение на большом массиве команд, которое показывает преимущество разделения труда по сравнению с фукнциональным подходом?
                                    0
                                    Вообще-то в этом случае вы имеете бутылочное горлышко в виде этого программиста; когда у вас много функциональности одновременно в разработке, это начинает реально тормозить.
                                    +1
                                    Статья правильная и нужная. Секретов она особых не содержит, но новичкам будет полезно знать, как может быть организован процесс разработки и поддержки ПО.
                                      +1
                                      Отлично! Очень практичная статья, касающаяся практически любой команды разработчиков.
                                        0
                                        Каждый раз, когда появляется такая статья, появляются бранчинг-срачи. А всё из-за чего? Статья написана с середины. Стратегии бранчинга и вообще CM и CI являются продолжением жизненного цикла конкретного проекта. А жизненный цикл у разных проектов разный.
                                        И вот уважаемый lair садится в лужу, применяя концепции CD туда, куда их применять нельзя.

                                        Only users with full accounts can post comments. Log in, please.