Подтвердить что ты не робот

Рефакторинг и параллельные ветки разработки

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

Как вы справляетесь с этой ситуацией на практике?

4b9b3361

Ответ 1

Я бы счел обязанностью разработчика технического обслуживания ветки объединить соответствующее изменение в текущее состояние соединительной линии. Существует несколько возможностей:

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

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

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

Ответ 2

Это, в конечном счете, вопрос о командной коммуникации, а не простой вопрос разветвления/слияния.

Первый шаг, как и во всех таких случаях, заключается в том, что у вас есть проблема. Это то, что вы сделали.

Затем вам нужно предупредить всю команду о проблеме.

Как только вы это сделали, я думаю, что есть два разных пути:

  • Если ветки обслуживания используются нечасто, скажем, что выпущенный код довольно зрелый и без ошибок, вы можете решить, что он заблокирован кодом. Каждый разработчик должен завершить работу над 32 октября и слить эти изменения обратно в багажник. Затем ветки должны быть либо закрытыми, либо замороженными. Затем работа может продолжаться в багажнике, и новое программное обеспечение может быть освобождено.

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

    После того, как trunk будет реорганизован, но прежде чем он будет очищен, отполирован, помечен и выпущен, просмотрите базу данных ошибок, особенно элементы, зафиксированные в ветвях, а не туловище. Они все еще актуальны? Теперь пришло время изменить код, если это необходимо. Это может означать двойную работу в течение короткого времени, но, надеюсь, код теперь намного удобнее обслуживать.

    После устранения всех известных проблем новая версия может быть выпущена, а старые ветки могут быть закрыты.

Ответ 3

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

Другой вариант - попробовать что-то вроде MolhadoRef (статья в блоге о MolhadoRef и SCM, ориентированном на Рефакторинг), если вы можете найти готовую для производства эквивалентную систему, которая соответствует вашим потребностям. Это, теоретически, рефакторинг-контроль источника. Я не заглядывал в это через некоторое время, но, в конце концов, я помню, что это было довольно далеко не просто чем-то вроде исследования и доказательств концепции.

Ответ 4

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

  • Шаг 1: Запустите рефакторинг компонента. На каждом шаге сохраните старый интерфейс, но попросите его перенести вызовы на новую реализацию. Обратите внимание, что это можно сделать несколькими шагами по мере создания нового интерфейса /API. Единичные тесты должны быть в состоянии проверить, что переход от старого к новому работает правильно, но этот шаг, скорее всего, по-прежнему будет нести накладные расходы /QA.

  • Шаг 2: новая версия работает в режиме реального времени; убедитесь, что все об этом знают. На данный момент новые функции не добавлены в старую версию, и все новые (или измененные) вызывающие абоненты используют новую версию.

  • Шаг 3: Найдите все (используйте инструменты для этого), который вызывает старый интерфейс, и измените все, чтобы вызвать новый интерфейс. Это, вероятно, также приводит к большому количеству накладных расходов на тестирование /QA. Каждый вызывающий может быть зафиксирован/выпущен по одному за раз.

  • Шаг 4: На этом этапе новая версия в прямом эфире, и нет доступных абонентов, которые обращаются к старой версии. Удалите его безопасно.

Обратите внимание, что, когда API является общедоступным, и вы не контролируете людей, которые его называют (например, Microsoft, например), вы, возможно, никогда не сможете пройти шаг 2.

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

Ответ 5

Учитывая, что большая часть затрат на исправление ошибки воспроизводит проблему и тестирует исправление. Можете ли вы написать автоматизированный тест, который будет работать во всех ветвях, даже если исправление кода должно выполняться по-разному для каждой ветки?

Ответ 6

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

Ответ 7

Создайте ветвь обслуживания и выполните ее как буфер между соединительной линии и ветвями версии.

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

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

Ответ 8

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

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

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

Ответ 9

Я вижу два отдельных способа решения этой проблемы:

1.

Значительные изменения в багажнике (например, основной рефакторинг) не должны выполняться в багажнике. Они должны быть сделаны в ветке и слиты обратно в багажник, когда они достаточно стабильны.

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

После того как изменения в ветвях обслуживания были сделаны, они затем могут быть объединены обратно в магистраль.

2.

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

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

Фактически каждая ветвь обслуживания становится "вспомогательной магистралью".

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

Ответ 10

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

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

Ответ 11

У вас есть есть, что многие ветки работают?

Была ли работа над стволом только начата, когда это было сделано, потому что в плане проекта говорилось, что текущий релиз будет готов к отправке, поэтому он был отправлен?

У вас есть много веток по обслуживанию, потому что по какой-то причине клиенты отказываются обновляться до последней версии? Если так, обратитесь к причине.

У вас слишком много старых выпусков, потому что разрыв перед следующим основным выпуском слишком велик?

Вы взимаете плату с клиентов, которые не будут модернизировать больше для обслуживания, так как это будет стоить больше?

Ответ на комментарий:

Microsoft по-прежнему поддерживает Windows XP даже несмотря на то, что Vista отсутствует

Это правда, однако Microsoft не поддерживает Windows XP SP1, хотя XP SP3 отсутствует.

Это не черное и белое, даже если вы не можете остановить поддержку старой версии, вы можете уменьшить количество старых версий, которые вы поддерживаете. Проблема в том, что Sales/Support любит говорить "да", но развитие получает боль, поэтому вам нужно, чтобы ваши продавцы/поддерживали людей на стороне.

Ответ 12

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

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

Ответ 13

В нашем проекте мы не в основном исправляем изменения в ветвях поддержки версий. Если есть ошибка и

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

Ответ 14

Как указал Грег, существует несколько возможных сценариев.

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

Мы разработали инструмент под названием Xmerge (cross-merge), который является первым шагом к слиянию с рефакторингом. Он еще не автоматичен, но он помогает справляться с жесткими слияниями, связанными с перемещенным кодом. Он описан здесь и уже интегрирован в Пластик SCM 2.7.

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