Quick background: we're a small web agency (3-6 developers at any one time) developing small to medium sized Symfony 1.4 sites. We've used git for a year now, but have previously used Subversion.

For the past 6 months we've put a lot of development time into a central Symfony plugin that powers our custom CMS. This plugin includes a number of features, helpers, base classes etc. that we use to build custom functionality. This plugin is stored in git, but branches wildly as the plugin is used in various products and is pulled from/pushed to constantly. The repository is usually used as a submodule within a major project.

The problems we're starting to see now are a large number of Merge conflicts and backwards incompatible changes brought into the repository by developers adding custom functionality in the context of their own project.

I've read Vincent Driessen's excellent git branching model and successfully used it for projects in the past, but it doesn't seem to quite apply well to our particular situation; we have a number of projects concurrently using the same core plugin while developing new features for it.

What we need is a strategy that provides the following:

  • A methodology for developing major features within the code repository.
  • A way of migrating those features into other projects.
  • A way of versioning the core repository, and of tracking which version each major project uses.
  • A plan for migrating bug fixes back to older versions.
  • A cleaner history that's easier to see where changes have come from.

Any suggestions or discussion would be greatly appreciated.

  • Always merge back to mainline as soon as possible. Every project should use the same base library, only with (maybe) some features enabled/disabled. Develop features against mainline, too. You now feel the pain that happens when forks diverge.
    – Wilbert
    Nov 5, 2013 at 9:10
  • This may help: nvie.com/posts/a-successful-git-branching-model Nov 5, 2013 at 12:50

6 Answers 6


I feel your pain as I deal with this sort of thing every day. My situation is having to maintain multiple customer versions of an open source project, each with a different selection of plugins, core hacks, etc. It's not fun when you have 50 of them.

I've not yet found an ideal (perfectly clean) solution, but my modifications to GitFlow are:

  • Make a separate branch (other than master) for each customer's production code. Use master for the definitive all-features version, and only merge what the customer wants into their own ones.
  • Keep developments (or added plugins etc) on tightly defined hotfix and feature branches, and leave them in place, even once merged, so you can merge into other customer branches if you need to. This also makes it easy to keep track of who has what features by crunching through the logs.
  • When developing new features, branch from the latest common ancestor of all customers if possible. This means that you will be able to merge into develop and then master, but also merge into the customer production branches without (in theory) causing conflicts.
  • Have one main repo just for development work, which looks like GitFlow. Have another that has your dev repo as a remote, which is used to store customer branches so that your dev repo has a clean(er) history.
  • If you really can't resolve a conflict easily and need to cherry-pick a whole branch at once, use rebase --onto like this. Just make sure it's clear in the commit messages where the feature cam from and why it's not been merged normally.

Using git has had an added side benefit in that we can now run a cron job across all the production servers which checks for unstaged files in the git repos. We now know if the support staff have been dicking about with the production code on the servers without telling anyone, which has prevented a lot of headaches :)

Hope that helps.

  • 1
    I have since solved this a different way, by telling all customers that they are getting the same build whether they like it or not. We then turn features on and off in the site's GUIs, and upgrade all customers at the same time. This has been remarkably effective, and has made our work easier and the customers happier as they get better support. Jan 13, 2015 at 1:20
  • I would turn this comment into an edit to the answer
    – ClintM
    Feb 7, 2017 at 21:58

The main mistake in this flow is creating customer branches!!! The only possible branches are new library features, not customer ones.

It's common library, so it should deliver API that COULD BE overridden by customer classes (from features requests). But this customized classes should be in client main project repository!

Your developers writes too highly coupled code. Read articles about code modularity, injections, interfaces, etc. That will reduce you pain a lot!

Second thing is proper flow for libraries. You should develop versioned libraries (e.g. 0.5, 0.7, 1.0, 1.2). Problem with library is different versions usage for different projects. Git flow doesn't support this in proper way (only last release and current development). I'm just in search for proper supporting tool for this type of flow.

Summarizing - you main pain lays in bad library code. You developers have to write code with default behaviour, free of clients behaviour and with API allowing overriding default one.


Shared code is more expensive to develop and maintain. It has to work in multiple scenarios; it must be backward compatible; and it should have test cases to ensure changes do not break existing clients.

As a general rule, shared functionality is worth it only if it's used in three or more places.

developers adding custom functionality in the context of their own project.

A custom change for one or two projects should not make it into the shared code. If you allow this, the shared code will quickly increase in complexity, up to a point where it becomes impossible to maintain. No workflow can help against that.


I use branches for short-lived code changes - usually days to a week or two.

Branches should be used purely for managing new features/fixes/upgrades/chores, they should not be a mechanism for managing product features themselves.

One option is multiple master for each product but that doesn't address the need to keep common code in sync.

Seem like you need to develop software / API's / configurations that let you configure these things through switches without changing code.

The main 'long-lived' branches that I expect to see are versions for non-application related differences such as ruby and/or rails versions.


Agree with Matt Gibson on his own answer.

We have the same situation in our company, and handling multiple versions of the same repository to multiple customers was done in the past and shows to be inefficient. The best solution we found was to transform our solution into a product with possibility to enable / disable features by configuration (only coders can do it, not the customer). This proved to be good by following reasons:

  • Easier to maintain the code, since there's only one repo.

  • Customers with high rate of updates (weekly) get bugfixes and small "free" features, making them happier. This is also important to keep the code updated with the frameworks and CMS we use, as well as ensuring security fixes.

  • Customers with low rate of updates or with no maintenance contract have a custom branch with a snapshot of an earlier and not updated version, allowing to fix only critical bugs (and we also fix them on master, so there's nothing unique on these older branches) . This is a approach we avoid, but since a specific customer does not want to pay for updates, this is how we handle it.

  • New features are available for the customers with reasonable frequency, allowing our commercial team to propose them. Very often this works, meaning we can sell features that are already functional, so they do not have to wait for their development and the cost is reduced, since it's a shared feature.

So, I think the best option is to rethink about what you have. It's not about branches, but about the product you company have.


This sounds more like a dependency management problem rather than a versioning problem.

How about using something like composer? You define what dependencies each project uses, and which versions (ex: 1.2.x) of those projects are acceptable. When you update your shared components, your dependent projects will not update automatically. You have to explicitly tell composer to update dependencies for a given project.

When you update a project's depenencies, you can ensure everything still works before you commit the dependency update. This gives you a chance to try things out safely.

There is a lot of resourcess in the Composer docs which should point you in the right direction.

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