Maintenance de deux versions de logiciel distinctes à partir de la même base de code dans Version Control

45

Supposons que j'écris deux versions différentes du même logiciel / programme / application / script et que je les stocke sous contrôle de version. La première version est une version gratuite "de base", tandis que la seconde est une version "Premium" payante qui reprend le code de base de la version gratuite et la développe avec quelques fonctionnalités supplémentaires à valeur ajoutée. Tous les nouveaux correctifs, correctifs ou fonctionnalités doivent se retrouver dans les deux versions.

J'envisage actuellement d'utiliser masteret developbranches pour la base de code principale (version gratuite) aux côtés master-premiumet develop-premiumbranches pour la version payante. Lorsqu'une modification est apportée à la version gratuite et fusionnée dans la masterbranche (après des tests approfondis developbien sûr), elle est copiée dans la develop-premiumbranche via la cherry-pickcommande pour plus de tests, puis fusionnée master-premium.

Est-ce le meilleur flux de travail pour gérer cette situation? Existe-t-il des problèmes, mises en garde ou pièges à prendre en compte? Existe-t-il une meilleure stratégie de branchement que ce que j'ai déjà proposé?

Vos remarques sont très appréciées!

PS Ceci est pour un script PHP stocké dans Git, mais les réponses devraient s’appliquer à n’importe quel langage ou VCS.

Joseph Leedy
la source

Réponses:

83

Au lieu d'avoir deux versions de code avec une base commune, vous devez concevoir votre application de manière à rendre ces fonctionnalités haut de gamme enfichables et pilotées par la configuration plutôt que par différentes bases de code.

Si vous avez peur de livrer ces fonctionnalités premium (désactivées par configuration) avec la version de base, vous pouvez toujours supprimer ce code lors d'une étape de construction / conditionnement finale et ne disposer que de deux profils de construction.

Ayant cette conception, vous pouvez également expédier 5 saveurs différentes et devenir très flexible, permettant même peut-être à des tiers de contribuer.

OliverS
la source
2
Oui, c'est ce à quoi j'ai commencé à penser hier soir avant d'aller me coucher. Merci!
Joseph Leedy
3
Windows moderne est conçu de cette manière, toutes les versions ont le même code et des fonctionnalités déverrouillées en fonction de la clé de licence utilisée.
Mooing Duck
39

Je recommande fortement de ne pas utiliser de branches à cette fin. En général, vous devriez envisager des branches pour les éléments qui seront (ou pourraient être) fusionnés ultérieurement (ou pour les branches de publication, où vous arrêterez éventuellement le développement d'une des branches). Dans votre cas, vous ne fusionnerez jamais vos versions "de base" et "premium". Elles seront toutes deux conservées indéfiniment. Les branches ne sont donc pas appropriées.

Conservez plutôt une version commune du code source et utilisez la compilation conditionnelle (par exemple, #ifdefen C / C ++, vous ne savez pas quel est l'équivalent pour PHP) pour inclure ou exclure les sections de code qui diffèrent entre "basique" et "premium".

Il semble que PHP ne possède peut-être pas une telle fonctionnalité de compilation conditionnelle, vous pouvez donc utiliser le préprocesseur C ( cpp, vous l'avez probablement déjà) pour prétraiter votre code source commun et produire à partir de là un "basique" et un "prime". version sans les directives du préprocesseur. Bien entendu, si vous choisissez de le faire, vous devez utiliser makequelque chose de similaire pour automatiser le processus d’exécution du préprocesseur.

Greg Hewgill
la source
Ce que vous dites sur les branches est tout à fait logique! Peut-être pourrais-je plutôt créer un référentiel séparé contenant uniquement le code Premium et utiliser une sorte de script de version ou un sous-module pour le combiner avec le code de base? Cela pourrait rendre TDD plus difficile, cependant ...
Joseph Leedy
14
Créer un autre référentiel est encore pire que créer des branches! Vous voulez certainement choisir une solution qui implique le moins de duplication de code versionné.
Greg Hewgill
2
Le second objectif est de ne contenir que le code supplémentaire, et non une autre copie de l'application dans son ensemble.
Joseph Leedy
1
Ah je vois, cela ressemblerait davantage au modèle "plugin", où votre code de base a la capacité de charger et d'exécuter des plugins (s'ils existent). Le code du plugin est séparé et fournit les fonctionnalités premium.
Greg Hewgill
4
@Joseph: l'utilisation de deux dépôts n'est appropriée que si le contrôle de version des deux bases de code est presque indépendant l'un de l'autre. Si ce n'est pas le cas, je vous recommande fortement de faire ce que Greg a écrit et de tout garder dans un même dépôt. La seule chose que je repenserais est l'utilisation du "préprocesseur C". J'imagine qu'un petit script écrit dans la langue de votre choix (PHP lui-même convient, Perl ou Python encore meilleur) qui crée une copie de votre code sans les fonctionnalités premium (légèrement indiquées) ferait l'affaire.
Doc Brown
8

Nous utilisons 2 projets distincts, le projet Basic et le projet Premium, qui dépend du projet Basic. Ne pas utiliser de braches, ils sont généralement utilisés pour les fonctionnalités.

Silviu Burcea
la source
Cela me plaît, car vous pouvez utiliser votre script de construction pour automatiser la création de programmes de base et premium.
Neontapir
1
En règle générale, vous avez besoin de 3 projets: une partie commune, souvent organisée en bibliothèque, et des parties personnalisées pour deux versions différentes.
Andriy Tylychko
3

Bien que la plupart des réponses actuelles soient en faveur de la compilation conditionnelle au lieu de branches, il existe un scénario dans lequel l’utilisation de branches présente un avantage évident: si vous décidez (maintenant ou plus tard) de rendre disponible le code source de la version de base, y compris tous les fichiers. l'historique des versions mais en excluant toutes les fonctionnalités premium, vous pouvez le faire avec l'approche branches mais pas avec une compilation branche et conditionnelle unique.

Je vous déconseille de choisir les cerises et de fusionner toutes les modifications de la version de base à la version premium. Il ne devrait y avoir aucune fonctionnalité ou correction de bogue incluse dans la version de base mais manquante dans la version premium. Pour rendre les choses aussi simples que possible, vous devez vous assurer que la branche Premium modifie le moins possible les fichiers communs. La branche premium devrait donc contenir principalement des fichiers supplémentaires, ainsi que de légères modifications des instructions de construction. De cette façon, les modifications apportées à la version de base fusionneront automatiquement sans causer de conflits.

La réponse de Greg a suggéré que vous «envisagiez des branches pour des choses qui seront (ou pourraient être) fusionnées à nouveau plus tard». Avec l'approche que je viens de décrire, c'est le cas, sauf que la branche finale pour tous les commits ne sera master-premiumpas master(ce qui est en fait master-basic).

Les sous-modules seraient bien sûr également une option. Cela dépend de votre processus de construction, mais si vous pouvez transformer la version Premium en un projet qui utilise la version de base en tant que module, tout ira bien. Cependant, vous aurez peut-être plus de mal si, à un moment donné, vous choisissez de sélectionner des fonctionnalités de la branche premium dans la branche de base. Avec les sous-modules, une telle modification serait représentée par deux commits distincts, alors que pour les branches, il s'agirait d'un seul commit pour la version de base, et la prochaine fusion dans la version premium saurait que ces modifications sont déjà incluses et n'ont pas être fusionné à nouveau.

MvG
la source
0

Dans le «matériel», cela se fait souvent, ce sont des systèmes vendus pour contrôler les dégâts, désolé, je ne me souviens plus comment ils s'appellent.

Une fois que la machine à laver «milieu de gamme» est expédiée, le code ne change pas, sauf pour une correction de bogue très importante, même lorsque le même code est modifié dans la machine à laver «bas de gamme» livrée quelques mois plus tard.

Les clients ne s'attendent pas à obtenir une mise à niveau d'une machine à laver qu'ils ont déjà apportée, un nouveau modèle n'est pas expédié tous les quelques mois.

La plupart d'entre nous n'habitons pas dans ce monde, alors faites ce que Greg dit sauf si vous écrivez un logiciel pour machines à laver.

Ian
la source