2

My company currently has SVN as main version control and we are in process of migrating to Git. Doing that is a perfect chance to do a structure reorganization.

Before I get to that let me describe current situation and our use cases. We have one main product and 20-ish clients which have customizations in place. What that means is that if client A wants a module from project customized to his own needs, we would do that.

So currently we have a default version in place which has its own repository. Each client has its own repository separated from the default one. The logic is that a client repository through composer.json shows on specific tagged default version. With some inner logic, overrides take precedence on client projects so that we don't touch the main project when it comes to customizations. SaaS is not a possibility, we need on premise installs.

Although this is the only way I currently see as a model which suits our needs, I find it rather cumbersome to have to maintain 20 repositories instead of one.

Solutions and why they don't work

  1. My initial idea was having a git submodules. This would however be absolutely the same with the current situation as I couldn't unify repositories
  2. Other idea was to have a single repository with Clients folder, and then set Jenkins to grab a specific folder depending on what project is being built. This however fails because clients have strict requirements of when and how the updates will happen and we can't force it on them. This means that if clients have a v1.0, we do have a contract to deliver fixes, but they are not obliged to go to v2.0. So in this configuration, I can no longer target v1.0 if development went forward
  3. Last but not least, I had a plan of having Git flow set up where each branch would be a separate client...thus also having master, dev and feature branches for each client, meaning that one repo would have about 20*3=60 branches minimum. While this is manageable with some strict rules, I have an issue here because if I have 20 clients on v1.0 and one of them notices a bug in version, I need to do a fix on master and then propagate that fix by hand to each branch. Even worse, if default master went on with development and is currently at v2.0, introducing a quickfix would mean cherry picking commits and propagating it to other X branches.

Is there any other solution that would fit my model which I'm not seeing here?

Norgul
  • 149
  • 5
  • which language / platform are you using ? some have good tooling to help with this sort of problems while others not so much. This in turn can help decide which option would work better, or perhaps propose new options you might nor have considered. – Newtopian Apr 02 '19 at 13:02
  • Its a PHP based project on a custom framework – Norgul Apr 02 '19 at 20:09

3 Answers3

3

To me, it's a decision between single repo and repo per client. As you also said, the branch per client idea doesn't seem reasonable to me (too complicated, no advantages).

Now, I've been working with both approaches, and the advantages of a single repo over multiple repos are to me:

  • Ease of development: one checkout gets all the clients, no need to set up 20 workspaces (git submodules could also help)
  • Tags and branches hold all the code: there's only one v1.0. If I understood it correctly, you use the same version number across all clients, so that's an advantage for you.

You had concerns about customers still being on the 1.x branch, while others are already on 2.x. I suggest using branches for this. While your master branch contains the 2.x code, you could still work on the 1.x code on another branch, and start releases from that one.

In one project, we called this "generations". While there was a master, branch generation/1.x was also worked on, and we started bugfix, release or even feature branches from it. You can always cherry pick (SVN: "merge") commits between generations (or master). Finally, if one customer moves on to 2.x, you could move his directory over to master (or whatever generation is appropriate).

To me, the major concern would be scaling (or repo size): if the number of your clients grows, or your codebase takes lots of disk space, a single repo might get hard to handle.

fxnn
  • 144
  • 5
3

We have one main product and 20-ish clients which have customizations in place

This kind of separation is not one that source control is designed to support. You should have one repo per client.

Rather than have the entire codebase replicated per client you should change your code, splitting it into as many libraries as possible*, each with its own repo. The goal being to maximise the number of libraries that can be shared across all the clients and thus only require a single repo per library

*whilst being sensible about responsibility boundaries and loose coupling

Ewan
  • 70,664
  • 5
  • 76
  • 161
  • without knowing more this would seem the most sensible approach. the client repo, ideally, would contain next to no code at all but rather just the assembly instructions to gather which version of which library and how to configure / assemble them into the desired customized solution. Bonus of this approach is that it becomes much easier to share development with other customers (perhaps by selling new functionalities that customer A paid for for other customers that have not... yet) – Newtopian Apr 02 '19 at 13:05
  • This is exactly how the project is organized now. I thought it was clear when I wrote that clients show to default version from its composer config. Only minimal set needed to run the customization is in the client repo. There is no default repo duplication – Norgul Apr 02 '19 at 20:08
2

I’m going to cut the knot and offer an entirely different solution:

Instead of shipping different code for different clients out of different repositories, I would instead unify all the code, ship versions, and control customizations via configurations, or, where there is no conflict between what customers want, ship one client’s customizations as features or enhancements for other clients.

This is of course in part a business decision, but it is one that might be worth floating if the specifics of your application supports it.

Williham Totland
  • 506
  • 1
  • 4
  • 8
  • Well so far the logic was to keep all the code which can be a part of the default solution unified, and versions are shipped as such. Problem arises when a client wants one part to behave in one way, while other one wants another. I don't think it is possible to split that kind of behaviour as a feature since it would require having a ton of flags since one feature may affect multiple classes? – Norgul Apr 11 '19 at 19:24
  • @Norgul Well, with a centralised configuration provider it's not necessarily a ton of flags; it's really just one that defines one suite of behaviour. Now, if a lot of customer-specific code is conflicting, then yeah, this isn't necessarily a great solution, but under the assumption that what's important to customers is more or less stochastic, it can work. – Williham Totland Apr 11 '19 at 19:26