Стратегия ветвления Git для долго не выпускавшегося кода

15

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

Традиционно у нас были ветки функций для каждой истории, и мы объединяли их сразу с мастером, когда они проходили тестирование. Тем не менее, мы хотели бы начать сдерживать выпуск законченных историй в эпосе, пока эпос не будет считаться «завершенным». Мы выпустим эти функции в производство только тогда, когда весь Epic закрыт. Кроме того, у нас есть сервер ночной сборки - мы бы хотели, чтобы все закрытые истории (включая те, которые являются частью незавершенных эпосов) были автоматически развернуты на этом ночном сервере.

Есть ли какие-либо предложения о том, как управлять нашим репо для достижения этой цели? Я подумывал о введении «эпических ветвей», где мы объединяли закрытые истории с соответствующей эпической веткой, а не напрямую, чтобы овладеть ими, но мои проблемы:

  • Я беспокоюсь о конфликтах слияний, которые могут возникнуть, если эпические ветки долго остаются открытыми
  • Ночные сборки потребовали бы объединения всех эпических веток в ветку "ночной сборки". Опять же, могут возникнуть конфликты слияния, и это должно быть сделано автоматически
Ситати
источник

Ответы:

23

Простое предложение: не делай этого.

Ветви git не предназначены для длительных форков кода, как описано здесь и https://blog.newrelic.com/2012/11/14/long-running-branches-considered-harmful/ . Ветви лучше всего рассматривать как переходные процессы, используемые для организации коммитов отдельным разработчиком на повседневной основе. Поэтому, если у них есть имя, которое соответствует чему-то, менеджер проекта (не говоря уже о конечном пользователе) может позаботиться о том, чтобы вы что-то делали неправильно.

Рекомендуемая практика - использовать непрерывную интеграцию с переключателями функций или ветвлением за абстракцией, чтобы гарантировать, что:

  • весь код всегда интегрирован (хотя бы каждый день, желательно чаще)
  • то, что развертывается, находится под явным контролем.
Сору
источник
1
Я подозревал, что это может быть популярным ответом! Моя основная проблема в этом заключается в том, чтобы постоянно поддерживать как «живую», так и «следующую» реализацию, а также необходимо, чтобы разработчик, работающий над функцией, знал заранее, чтобы создавать изменения как новые параллельные функции вместо обновления (/ замены) существующий функционал. Думаю, это требует больших изменений в мышлении в команде.
Ситати
Можно использовать ветки для разработки кода, просто никогда не используйте их для хранения кода. Поэтому, если вы не уверены, является ли задача 30-минутным исправлением или 2-недельной переработкой, начните с ветки. Как только вы знаете, либо слияние, либо рефакторинг к абстракции / переключению, затем слияние.
сору
@Sitati: Я только что слил код, который был в ветке функций в течение последних четырех месяцев. Тем временем develмы перешли на CMake из Autotools, представили Travis CI, переработали код. В конце концов, было проще понять новую функцию и применить ее вручную, develчем пытаться объединить ее. У нас также были новые магистранты, разработавшие новую функцию в отрасли, которую они разветвляли, когда начинали свою диссертацию. Через год они отодвинули его, и не было никаких попыток вернуть его обратно, поэтому с каждым днем ​​становилось все труднее.
Мартин Юдинг,
2
Связанному сообщению в блоге уже 5 лет. Я ненавижу функцию переключателей. Что плохого в долгосрочном ветвлении, регулярном слиянии обратно с ветвью функций из основного и добавлении непрерывной интеграции к ветке долгосрочных функций?
Джейсон Келли
CI - это имя процесса, а не инструмента. Если у вас более одной ветви функций, они обычно не будут непрерывно интегрироваться друг с другом. Что означает нахождение проблем позже, а не раньше.
сору
1

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

например.

У меня есть функции A, B и C для v2 моего продукта. B и C связаны, я не хочу выпускать B, если C также не закончен.

У меня есть три разработчика, которые работают одновременно над функциями.

У меня есть набор в камне дата выхода D

B закончен и объединен, A закончен и объединен. C задерживается ... что мне делать ?!

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

Решение более человечное. Вы пропустили дату релиза и должны отменить ее.

Ewan
источник
1

Это сложная проблема, но многие сталкиваются с ней. Я предпочитаю использовать настройку Gitflow в качестве отправной точки.

Разработка -> Новые работы над
Master -> Готовые работы, требующие тестирования Производство -> Материал, опубликованный для производства.

При небольших (более коротких) возможностях я создаю ветку от разработки, делаю работу там, затем объединяю ветку с разработкой.

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

Через равные промежутки времени (в зависимости от проекта) я объединяю разработку с мастером, и начинается цикл тестирования. Если в тестировании появляются какие-либо исправления, они вносятся в основную ветвь (тогда подветвь объединяется). И разработка может продолжаться в основной ветке во время тестирования.

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

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

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

Мое нормальное дерево выглядит так

 LongTerm -> Development -> Master -> Production    
 LongTerm <- Development      |            |  
     |       Development -> Master         |  
 LongTerm <- Development -> Master         |  
             Development <- Master         |  
                            Master -> Production  

По моему общему правилу, ни одно изменение не должно занимать более нескольких часов. Если это так, то его нужно внести в более мелкие изменения. Если это огромная функция (например, переписывание пользовательского интерфейса), то это происходит в долгосрочной перспективе, так что нормальная разработка может продолжаться в то же время. Ветви LongTerm, как правило, являются только локальными ветвями, в то время как Development, Master и Production являются удаленными ветвями. Любые подотрасли тоже локальные. Это сохраняет репозиторий в чистоте для других, не теряя полезности git для долгосрочного набора функций.

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

coteyr
источник
«По основным (долгосрочным) функциям я создаю ветку из разработки» - разве вы не должны создавать новые ветви функций (разработки) из производственной ветви? Видя, как ветка Production является готовым к выпуску кодом.
роботрон
Нет, производство уже выпущено, мастер опережает производство, а развитие опережает мастера. Новая функция, такая как добавление налога к сумме заказа, не имеет смысла, если вы не работаете с кодом, в котором уже есть заказы.
coteyr
Но если вы переходите от dev, а затем объединяетесь, не будет ли эта ветвь (и, следовательно, master и Production позже) включать все изменения dev, сделанные другими до момента ветвления? Некоторые из этих изменений могут не иметь одобрения QA. Возможно, речь шла о разных подходах к управлению релизами.
роботрон
Да, так и есть. QA тестирует определенный SHA в master, но вы не можете удержать dev для этого.
coteyr
«QA тестирует конкретный SHA в мастере» -> QA тестирует каждую новую функцию как отдельную? Позвольте мне выполнить типичный сценарий, с которым сталкивается моя команда: скажем, у вас есть 2 длительных проекта в одной кодовой базе: Проект A находится в QA в прошлом месяце и будет QA'd еще в течение месяца. Проект B находился в разработке в течение последних 6 месяцев и теперь готов к QA. Проект A объединен с главным и определенно не готов к производству из-за многочисленных незначительных ошибок бизнес-правил. Как мы справляемся с проектом B? A и B должны быть проверены вместе, чтобы проверить взаимодействие (B не вызовет конфликтов во время слияния).
роботрон