We are maintaining and developing a huge web application (http://www.popscan.com/ for those interested. Trust me. It's nothing YOU would want to buy :p ) which we also have to heavily customize for various customers and their very special wishes (even though I'd rather not as you'll see).

Some of these installations, we host ourselves, some are hosted by our customers.

We maintain a development head which becomes a release branch every 6 months. This is the core of our application and development done to the core is then part of the new release we give our customers either as part of a maintenance contract or for an upgrade fee.

Early on, we found that it's impossible to give all customers the same solution. Heck, it's not even possible to give them the same version with a completely altered skin. Part of this could be that we have fierce competitors in our customer base, so they want some way to differentiate.

So this is what we have invented the "Customizers" for. Our app is sprinkled with Hooks (currently 305, but steadily increasing) that a customizer can hook into altering just about any behavior that a customer could possible want to have altered. Sometimes it's just for altering data, sometimes, you can outright replace functionality.

That worked quite well, but over time, we needed even more power at which point we added even more stuff like pluggable modules (think very powerful controller if you come from a Rails world), pluggable amendments to existing modules and most recently template overrides:

Our application comes with three base styles (consisting of Smarty (yeah. it's PHP, but quite clean. And 6 years old) templates plus basic CSS and JS) plus a customer specific theme (consisting of CSS plus images).

Of course, sometimes not even that is enough which is why we can now inject smarty code based on the customer at which point our application will load the overridden template instead of the original.

Let me tell you this: This customization is the most painful thing I have ever done in my life. Even though the core application is the same for all our customers, no two apps look (or even work) the same. Hours and hours are spent tweaking every aspect of the application to the customers demand, sometimes even turning cool features off because "it looks to similar to what competitor B has".

None the less: Using the strict separation between core and customization, we can move the product forward without filling the core with customer specific crap and without constantly merging.

It's true: We don't need customer specific branches.

There's just the HEAD and the bi-yearly release branches (auto-deployed weekly to the systems we host). Customer specific changes are done in the customization part of the application and by design they can't affect the core (or, heaven forbid, the customization of another customer).

The only merges we do is the "Friday-merge" in which we forward-port bugfixes made to the release-branches - from oldest to newest to master.

This is where git is really awesome in that it's extremely good at merging making these friday-merges a pleasure to do.

Doing them weekly on a set time removes the need for each developer to manually merge every change (unless they need it in another branch - then they have to cherry-pick) and doing it weekly means that the changes are fresh enough for whoever does the merge to remember what the nature of a change was should a conflict arise.

So while the thing still is a huge, marketing-driven mess, we DO have it under control and are still able to move the product itself forward without the need of having to track a branch per customer (we tried that. it turned out much worse).

In the perfect world though, the customization would not exist and our customers would use the same product maybe with some styling using CSS, but unfortunately, that's plain not possible (for other technical reasons too, but this is already getting long).