Consider this - In 'extended' Git-Flow, (Git-Multi-Flow, sounds catchy, anyone?), every developer working for customer XYZ configures, for example:
- name of target core master branch: master-XYZ
- name of target next-release integration branch: develop-XYZ
- naming scheme for feature branches: feature/*
- naming scheme for release branches: release/*
I've planned them to use DIFFERENT names for master/develop branches. That means that for each customer, I have separate next-release integration branch, and a different version of the current-release branch.
What does it give? Any developer that works on a feature (be it patch, customization, whatever) just uses git flow. But if they work in context of customer XYZ they will 'finish' the feature and it will be integrated on a dedicated develop-XYZ branch. When released, it will get merged into dedicated master-XYZ branch. No possibility of "leaking" features or customizations.
However, 'feature' branches are still normal. If at some point of time you want feature #100 (originally for customer ABC) and bugfix #321 (orig for customer DEF) you can still merge them to another customer like XYZ, provided that the differences in their relevant develop-?/master-? are not too different, but that's another story)
It's not that great actually. With decent amount of customers and separate devel/master for them, you will quickly notice that:
- if customers' customization are hard, they will diverge their develop/master often, not only in customized areas, but in the core code as well. That will impeded future feature sharing between them
- developers will get grumpy about having to change git-flow configuration constantly (swithc to master-FOO, switch to master-BAR, master-XYZ), or, having to keep several repo copies, configured to different customers
- having separate develop/master is almost like having separate repos, but change notifications will spam everyone
- (..)
That's for starters. Some of them can be mitigated. The second point can be solved by noticing that git-flow setup just a few lines in the .git/config file, so you don't need to re-config gitflow or keep several copies of the repo. Just edit the file. Or keep a copy of git-config and just flip that file. Or use some $ENV var to indicate current customer. Tenths of other ways to solve it.
Next thing, features. I deliberately didn't consider naming feature branches feature/XYZ/ but left simple feature/. Features don't have to be bound to customer. You can share/etc them later.
Next thing, releases. I deliberately didn't consider naming release branches release/XYZ/. You will not share them, ever, probably. You may. However, I suppose you already have a better naming for release branches than just prefixing them with customer name like releases/XYZ would do. You need to version number or date there as well. Maybe some feature set code name as well. I don't know. Invent something here.
Next thing, core master and develop. For customers, devs are working on develop-XYZ, master-XYZ. But you can still have core master and develop for working on improvements of the shared core code. No changes there.
Next thing, I said master-XYZ, develop-XYZ. But that does not have to be like that. You know about feature/.... So why not masters/XYZ & develops/XYZ? Sure, can do. You can even XYZ\masterand XYZ\develop and XYZ\feature\ but then, why not make separate repos like on GitHub, where you can Fork/Merge/PR one off another?
Git-Multi-Flow is an extension of vanilla Git-Flow, and with the latter naming scheme (XYZ\masteretc) you end up with something like multiple logical repos in a single repo. Kind of multi-tenant Git-Flow..
So.. It's possible. Not that hard to set up. But still 1000+ branched master/develop/etc sets, handled by the same group of teams will be a pain. There will be mistakes. Devs will mix up things from time to time, they're just people. From my experience, when "lots of customizations" happen, it's almost just URLs, ports, passwords, images, styles, text, maybe sometimes limited layout changes. Maybe one extra module here or there. You should be able to handle it all in core code, and turn it on/off/configure via configuration. This way the number of long-lived 'customization branches' (aka master-XYZ) will be greatly reduced, at the cost of more detailed configuration for each customer deployment.
That configuration should also be tracked and versioned (i.e again in Git). I hope you do it already. But it should sit in a different storage than code. It's a different thing. Managed by support or deployment team.