48

Let's say that I am writing two different versions of the same software/program/app/script and storing them under version control. The first version is a free "Basic" version, while the second is a paid "Premium" version that takes the codebase of the free version and expands upon it with a few extra value-added features. Any new patches, fixes, or features need to find their way into both versions.

I am currently considering using master and develop branches for the main codebase (free version) along side master-premium and develop-premium branches for the paid version. When a change is made to the free version and merged to the master branch (after thorough testing on develop of course), it gets copied over to the develop-premium branch via the cherry-pick command for more testing and then merged into master-premium.

Is this the best workflow to handle this situation? Are there any potential problems, caveats, or pitfalls to be aware of? Is there a better branching strategy than what I have already come up with?

Your feedback is highly appreciated!

P.S. This is for a PHP script stored in Git, but the answers should apply to any language or VCS.

5 Answers 5

83

Instead of having two code version with a common base you should design your application in a way to make those premium features plug-able and driven by configuration rather than different code bases.

If you are afraid to ship those premium features (disabled by configuration) with the basic version you can still remove that code in a final build/packaging step and just have two build profiles.

Having this design you can also ship 5 different flavors and get very flexible, maybe even allowing third parties to contribute.

2
  • 2
    Yes this is what I started thinking about last night before I went to bed. Thanks! Jun 11, 2014 at 11:48
  • 3
    modern Windows is designed this way, all versions have all the same code, and have features unlocked depending on the license key in use. Jun 11, 2014 at 19:55
39

I strongly recommend not using branches for this purpose. In general, you should consider branches for things that will be (or might be) merged back together again later (or for release branches, where you eventually stop development of one of the branches). In your case, you will never merge your "basic" and "premium" versions together, and they will both be maintained indefinitely, so branches are not appropriate.

Instead, maintain one common version of the source code and use conditional compilation (eg. #ifdef in C/C++, not sure what the equivalent is for PHP) to include or exclude the sections of code that differ between "basic" and "premium".

It looks like PHP might not have such a conditional compilation feature built in, so you could use the C preprocessor (cpp, you probably already have it) to preprocess your common source code and from that, produce a "basic" and a "premium" version without the preprocessor directives. Of course, if you choose to do this you should use make or something similar to automate the process of running the preprocessor.

10
  • What you are saying about branches makes total sense! Perhaps instead I could create a separate repo containing just the Premium code and use some sort of release script or a sub-module to combine it with the base code? This might make TDD harder, though... Jun 11, 2014 at 4:04
  • 15
    Creating another repository is even worse than creating branches! You definitely want to choose a solution that involves the least duplication of versioned code. Jun 11, 2014 at 4:06
  • 2
    The point of the second repo is to house just the extra code - not another copy of the whole app. Jun 11, 2014 at 4:07
  • 1
    Ah I see, that would be more like the "plugin" model, where your basic code has the ability to load and run plugins (if they exist). The plugin code is separate and provides the premium features. Jun 11, 2014 at 4:09
  • 4
    @Joseph: using two repos is only appropriate if the versioning of the two code bases is almost independent from each other. If that is not the case, I would strongly recommend to do what Greg wrote and keep everything in one repo. The only thing I would rethink is the use of the "C preprocessor". I guess a small script written in the language of your choice (PHP itself is fine, Perl or Python even better) which makes a copy of your code without the (somehwhat marked) premium features would do the trick.
    – Doc Brown
    Jun 11, 2014 at 4:23
8

We are using 2 separate projects, the Basic one and the Premium one that depends on Basic project. Do not use braches, they are usually used for features.

2
  • This appeals to me, because you can use your build script to automate the creation of both basic and premium programs.
    – neontapir
    Jun 11, 2014 at 6:11
  • 1
    in general case you need 3 projects: common part, often organised as a library, and custom parts for two different versions. Jun 11, 2014 at 11:39
3

While most current answers are in favour of conditional compilation instead of branches, there is one scenario where there is a clear benefit to using branches: if you (now or later) decide to make the source code of the basic version available, including all the version history but excluding all the premium features, then you can do so with the branches approach but not with a single branch and conditional compilation.

I'd advise against cherry picking, and instead merge all changes from the basic version into the premium version. There should be no feature or bug fix included in the basic but missing in the premium version. To make things as painless as possible, you should make sure that the premium branch modifies the common files as little as possible. So the premium branch should mostly contain additional files, and perhaps some slight modifications to build instructions. That way, changes from the basic version will merge automatically without causing conflicts.

Greg's answer suggested that you “consider branches for things that will be (or might be) merged back together again later”. With the approach I just described this is the case, except that the final branch for all commits will be master-premium not master (which is actually master-basic).

Sub-modules would of course be an option as well. It depends on your build process, but if you can make the premium version into a project which uses the basic version as a module, that would be just fine. You might however have a harder time if at some point you decide to cherry-pick features from the premium branch into the basic branch. With sub-modules such a change would be represented as two distinct commits, whereas with branches this would be a single commit to the basic version, and the next merge into the premium version would know that these changes are already included and don't have to be merged again.

0

In “hardware” this is done often, they are systems sold to control the mess, sorry I can’t remember what they are called.

Once the “mid range” washing machine ships, it’s code is not change other than for a very important bug fix, even when the same code gets changed in the “low end” washing machine that ships a few months later.

Customers don't expect to get upgrades to a washing machine they have already brought, a new model is also not shipped every few months.

Most of us don’t live in that world, so do what Greg says unless you are writing software for washing machines.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.