Поддержка двух отдельных версий программного обеспечения из одной и той же кодовой базы в управлении версиями

45

Допустим, я пишу две разные версии одного и того же программного обеспечения / программы / приложения / скрипта и храню их под контролем версий. Первая версия является бесплатной «Базовой» версией, а вторая - платной «Премиум», которая использует кодовую базу бесплатной версии и дополняет ее несколькими дополнительными дополнительными функциями. Любые новые исправления, исправления или функции должны найти свое применение в обеих версиях.

В настоящее время я рассматриваю возможность использования masterи developответвлений для основной кодовой базы (бесплатной версии) вдоль стороны master-premiumи develop-premiumответвлений для платной версии. Когда изменение вносится в бесплатную версию и объединяется с masterветкой (после тщательного тестирования, developконечно), оно копируется в develop-premiumветку с помощью cherry-pickкоманды для дополнительного тестирования, а затем объединяется в master-premium.

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

Ваш отзыв очень важен!

PS Это для PHP-скрипта, хранящегося в Git, но ответы должны относиться к любому языку или VCS.

Джозеф Лиди
источник

Ответы:

83

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

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

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

Olivers
источник
2
Да, это то, о чем я начал думать прошлой ночью перед тем, как лечь спать. Спасибо!
Джозеф Лиди
3
современная Windows спроектирована таким образом, все версии имеют одинаковый код и разблокированные функции в зависимости от используемого лицензионного ключа.
Mooing Duck
39

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

Вместо этого поддерживайте одну общую версию исходного кода и используйте условную компиляцию (например, #ifdefв C / C ++, не уверенный, что эквивалентно PHP), чтобы включить или исключить разделы кода, которые различаются между «базовым» и «премиумным».

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

Грег Хьюгилл
источник
То, что вы говорите о ветвях, имеет смысл! Возможно, вместо этого я мог бы создать отдельное репо, содержащее только код Premium, и использовать какой-нибудь скрипт выпуска или субмодуль, чтобы объединить его с базовым кодом? Это может сделать TDD тяжелее, хотя ...
Джозеф Лиди
14
Создание другого хранилища еще хуже, чем создание веток! Вы определенно хотите выбрать решение, которое включает в себя наименьшее дублирование версионного кода.
Грег Хьюгилл
2
Смысл второго репо состоит в том, чтобы разместить только дополнительный код, а не другую копию всего приложения.
Джозеф Лиди
1
Ах, я вижу, это было бы больше похоже на модель «плагинов», где ваш базовый код имеет возможность загружать и запускать плагины (если они существуют). Код плагина является отдельным и предоставляет расширенные функции.
Грег Хьюгилл
4
@Joseph: использование двух репозиториев уместно только в том случае, если управление версиями двух баз кода практически не зависит друг от друга. Если это не так, я настоятельно рекомендую делать то, что написал Грег, и хранить все в одном репо. Единственное, что я бы переосмыслил, это использование препроцессора С. Я предполагаю, что небольшой скрипт, написанный на языке по вашему выбору (сам PHP в порядке, Perl или Python еще лучше), который делает копию вашего кода без (несколько отмеченных) премиальных функций, справится с задачей.
Док Браун
8

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

Сильвиу Бурча
источник
Мне это нравится, потому что вы можете использовать свой скрипт сборки для автоматизации создания как базовых, так и платных программ.
Неонтапир
1
в общем случае вам нужно 3 проекта: общая часть, часто организованная в виде библиотеки, и пользовательские части для двух разных версий.
Андрей Тиличко
3

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

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

В ответе Грега говорилось, что вы «рассматриваете ветви для вещей, которые будут (или могут быть) снова объединены вместе позже». При подходе я только что описал это так, за исключением того, что окончательное отделение для всех фиксаций будет master-premiumне master(что на самом деле master-basic).

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

MVG
источник
0

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

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

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

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

Ян
источник