0

I am writing a piece of software and and I am about to release three versions of it, a Lite version, a Pro version and an Enterprise version.

This three versions have some common features, but also, there are some features in each version, that is not present in other versions. Something like the following figure:

Software versions

To manage these versions, I have two approaches in mind (using git):

1: Create a branch for the common features, and another branch for each version. Then merge in the common branch into each version when needed.

2: Create a repository for the common features and fork it into three other repositories for each version. Then pull in the common feature from the main repo (upstream) into each version's repo, when needed.

I wonder which of these approaches is better or if there is a better approach (with or without using git) to achieve the result.

Update Unfortunately this software was originally written by some other guys, and it lacks structure. It is too coupled and most likely, it is not possible to break it down into smaller modules, unless written over from scratch.

4 Answers4

3

Allow me to be bold and suggest a different approach for this.

Instead of physically separating the code for the unique features of each version, it might make sense to have one binary but then, depending on what edition is in use, enable specific features through feature toggles.

This would give you the ability to ship specific editions while reducing the overhead of maintaining three distinct code bases, and allows you to easily include existing features into an edition if your business decides that is necessary.

JohnD
  • 3,884
  • 1
  • 28
  • 40
1

Both of your approaches sound OK, but I would probably pick the first one. From experience, having your code in one repository is less headache. On the other hand, having two repositories may enforce a better separation and dependency management.

Another approach would be to have your three products depend only on the binary of your common code. This gives you more flexibility and provides better tracking of build versions. In this scheme, you would periodically provide versiondo binary builds of the common code. Then, your three products can be their own repositories or three branches in the same repo or whatever. Furthermore, depending only on the binary ensures that no unwanted source depending creep in. A side benefit is that you can build your three products faster since you do not have to build the common source along with each product.

amahfouz
  • 2,328
  • 2
  • 16
  • 21
1

I'm reluctant to use Git for this, since it seems a lot more like a dependency problem more than a repository problem. Sure, there are ways to solve this via submodules, but they can be finicky to use.

I'd save submodules as a last-ditch effort, but let's consider some things about the dependencies for your program.

  • Lite
    • Most stripped down
    • Contains core functionality
  • Pro
    • Adds more functionality which builds on Lite and (maybe?) some of Enterprise
    • Does not contain code that Lite or Enterprise would consider "extra"
  • Enterprise
    • Adds more functionality which builds on Lite and Pro
    • Does not contain code that Lite or Pro would consider "extra"

The main thing we'd tease out is that each of these projects have a core set of code and functionality that we want to expose and allow the other projects to depend on.

Once that's actually teased out - as in, we now understand which parts of each project are shareable between apps - we would publish those artifacts, then specify each app to depend on one of them. I could envisage it going thus:

  • Lite depends on nothing
  • Pro depends on Lite
  • Enterprise depends on Lite and Pro

This is where a dependency manager comes in. They exist for most every modern language nowadays; for instance, if you were using Maven or Gradle, you could set each of these up as their own project, and publish the core modules to an internal repository directory somewhere in your company.

Git submodules might be able to cover it, but I'd strongly recommend going the other route and using a proper dependency manager.

Makoto
  • 104,088
  • 27
  • 192
  • 230
  • This approach works fine, only if the versions were dependent upon each other in the order you specified. But, there are some features in Lite version, which is not present in other versions and so on for the other versions. Maybe I am using the wrong names for the versions, but as I showed in figure (the three triangles) each version has it's own features, plus the common ones. –  Feb 20 '15 at 18:47
  • Yes, I realize this. This is why I'm saying that there's core functionality that *can* be shared between projects. You would then build the extra bits and bobs on top of that core module for each project (so lite would probably have a lite-extended module which depends on core). – Makoto Feb 20 '15 at 18:52
  • please read the update –  Feb 20 '15 at 18:53
  • No tool is going to solve the decoupling problem for you. I can appreciate that it may take energy to break it up, but you may have to exert that energy at this time so that you can attain the goal you want. – Makoto Feb 20 '15 at 18:54
0

I would create three repos, one for each version.

And then a forth repo with the common parts, which would be included inside the other three repos as a submodule. The rationale behind this is that you will likely want to be able to integrate different versions of the common part in your three versions (different version of the submodule). You also want to be able to develop the common part without forcing it upon any of the releasables.

This should be as flexible as your option 1 but without the crazy merging of the common part branch.

Martin G
  • 17,357
  • 9
  • 82
  • 98