Ветвление нарушает непрерывную интеграцию?

18

Я думаю, что эта статья, «Успешная модель ветвления Git» , очень хорошо известна среди опытных пользователей DVCS.

Я использую в hgосновном, но я бы сказал, что это обсуждение хорошо для любой DVCS.

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

Поэтому мы хотим настроить CI-серверы, такие как Jenkins, и улучшить наш рабочий процесс с помощью будущей системы обеспечения (chef, puppet, ansible и т. Д.).

Реальная часть

Хорошо, модель, представленная выше, работает хорошо, но ветви могут сломать CI. Ветвь объекта должна синхронизироваться с источником (согласно статье, это будет developmentветвь), чтобы сделать CI и слияние плавным, верно?

Скажем, Алиса и Боб работают над двумя функциями. Но Алиса закончила на следующий день. Особенность Боба занимает неделю. К тому времени, как Боб закончил, его изменения устарели (возможно, Алиса реорганизовала / переименовала некоторые классы).

Одно из решений - каждое утро разработчики должны master/originпроверять наличие изменений. Если Алиса зафиксировала, Боб должен вытащить и слиться со своим рабочим пространством, чтобы его ветвь функций была актуальной.

  1. Это хороший способ?
  2. Должны ли эти ветви существовать в главном репо (а не в локальном клоне?). Значение, что каждый разработчик должен иметь право коммитировать для главного репо в GitHub / Bitbucket, чтобы они могли создать новую ветку? Или это делается локально?
  3. Наконец, модель, представленная в статье, должна нарушать CI, если ветви не синхронизированы с origin/master. Так как мы хотим делать ночные сборки, должны ли разработчики собирать и объединять данные до того, как они уйдут с работы, и будет ли CI работать в каждой ветви функций?
CppLearner
источник

Ответы:

12

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

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

Что касается вопросов 1 и 3: разработчик несет ответственность за обеспечение того, чтобы сборка основной ветви разработки не порвалась, когда они объединяют свою функциональную ветвь с ней. Как они это делают, это их проблема, но есть два возможных пути:

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

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

Барт ван Инген Шенау
источник
Я согласен, что использование функциональных ветвей (немного) противоречит концепции CI. Тем не менее, это возможно создать систему CI , которая не требует изменений конфигурации для работы на художественных отраслях. (Я делал это в прошлом с некоторыми простыми скриптами на Python), и это может быть полезно, когда ваши «функциональные» ветки фактически используются в качестве веток стабилизации релиза, где CI абсолютно необходим.
Уильям Пейн
1
На самом деле, я думаю, что нам нужны две "центральные" ветви - одна как ветвь throwaway_integration, которая существует просто как быстрая проверка на слияние и тестирование для активно разрабатываемых функций, а другая ветвь "master" или "stable", которая содержит функции после того, как они достигли определенного уровня стабильности / зрелости. Разработчики извлекают стабильный код для работы из второй ветви "stable" / "master" и часто объединяют и помещают изменения в первую ветку "unstable" / "throwaway_integration". Конечно, тесты CI должны выполняться в обеих ветвях.
Уильям Пэйн
@WilliamPayne: Я считаю, что такую ​​«нестабильную» ветвь часто называют «развивающейся»
Барт ван Инген Шенау
5

В ответ на 1)

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

2)

В основном, ветки создаются в Mercurial путем клонирования репозиториев, поэтому вам не нужно предоставлять каждому разработчику привилегии коммитов для главного репозитория. Однако, возможно, вы захотите дать разработчикам возможность создавать клонированные репозитории на сервере непрерывной интеграции, поскольку не всегда возможно запускать тесты локально. (У меня когда-то была система CI, в которой модульные тесты выполнялись на 128-ядерном кластере в течение 8 часов). Разумеется, разработчики не могли выполнять локальные тесты.

3)

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

Уильям Пейн
источник
1
«В основном ветки создаются в Mercurial путем клонирования репозиториев» - это могло быть правдой в 2013 году, но в наши дни закладки Mercurial функционально эквивалентны веткам Git во всех, кроме имени.
Кевин
@ Кевин: Вы, скорее всего, правы. Я использую git (почти) исключительно с февраля '13 - примерно через месяц после того, как я написал вышеупомянутый ответ ... поэтому я не особо осведомлен о том, какие изменения произошли с Mercurial с тех пор.
Уильям Пейн
1

Вот как вы можете это сделать: функция ветвления.

  1. Для любой новой задачи (исправление ошибки, функция и т. Д.) Создайте новую ветку (например, bugfix-ticket123-the_thingie_breaks)
  2. Пока вы работаете, постоянно обновляйте и объединяйте default (или master в git) с вашей веткой возможностей . Это поможет вам обновить ветку без необходимости работать в ветке по умолчанию
  3. Когда ваша функция будет готова и ваши модульные тесты пройдены , затем снова потяните и объедините настройки по умолчанию в вашу ветку, закройте вашу ветку и протолкните ее без слияния , ваш интегратор заметит новую головку и что это закрытая ветка, поэтому он позаботится о его интеграции. Если у вас нет интегратора, переключитесь на значение по умолчанию и объедините ветвь функций со значением по умолчанию .

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

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

dukeofgaming
источник
Вы смешиваете и подставляете довольно ортогональные вещи. 0 конфликт слияния! = 0 неправильный юнит-тест, успешное слияние! = Успешный код
Lazy Badger
Добавил некоторые уточнения, забыл упомянуть, что юнит-тесты также должны пройти :)
dukeofgaming