Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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.

share|improve this question
    
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 '13 at 9:10
    
This may help: nvie.com/posts/a-successful-git-branching-model –  Michael Durrant Nov 5 '13 at 12:50

5 Answers 5

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.

share|improve this 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.

share|improve this answer

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.

share|improve this answer

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.

share|improve this answer

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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