Git – an effective git process for managing our central code library

gitversion controlworkflows

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.

Best Answer

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.