A few days ago, I simultaneously posted a question about source control structure to my blog and to LinkedIn Answers. My blog got one response. LinkedIn answers got, as of now, 14 extremely well-thought out answers (more are coming in every day). The quality of the answers is pretty remarkable, as is the fact that none of the people responding are people I know. They may be distantly connected to me on linked-in, but they aren’t on my contact list.
I’m super-impressed. While the app doesn’t have a friendly face (URLs are non-intuitive, information architecture is confusing, etc), this is an extremely valuable and practical result to get from a social app. I’ll definitely be posting more questions to LinkedIn! Answers are below the fold if you want to read them …
So at SlideShare we currently organize our source control branches by release. This works our pretty well (we can work on something that’s a month or two away from being ready, without messing up our ability to deploy other stuff next week).
But one thing I don’t like about this model is that it’s a little inflexible. If one feature on a release is taking more time than was planned, it’s hard (impossible?) to “unbundle” it from the other features and deploy a fraction of a release. In other words, removing a feature from a release is not straightforward.
I’ve heard some shops organized their source control by feature. This seems interesting (it removes the problem I’ve described above) but a little tricky (what’s a “feature”? Does every bug fix have it’s own branch? Seems to bring a lot of subjectivity into the system). Since their are probably several features in a release, this also greatly increases the amount of merging that has to happen to do a release.
Thoughts? Reactions? How are the branches organized in YOUR source control system?
I would say to keep things simple and to use the tools in the ways in which they were intended. Most VC tools I’ve used are not project management, collaboration or release management tools. Usually you have main development on the main branch, and uses branches for each release, with bugfixes occuring on those branches, to be merged later to the main trunk.
What you are talking about is really a project management issue; you should know what features are going into the release you are working on; if they aren’t going to make it, you wont’ always (or ever?) be able to depend on some automated tool to suck out the code for that feature.
I think that trying to use source control to organize features as you describe is overcomplicated your development and expending a lot of effort mitigating a risk that could be easier dealt with by frequent communication and better project planning.
Let your source code control system do it’s thing: creating and tracking versions of your software.
My company has a very complex branching system. First, there are release branches. Then, there are separate branches for geographically separate development teams. There are also feature branches and fix branches.
Feature is everything really big (and mostly with high risk of not being completed until the next release). Features are merged to release branch only after they’re stable and would not compromise stability of the release itself. If they’re not stable before the current release, the will simply go to the next one.
Once the release is finished, everything goes to fix branch. It can be merged to new release’s branch any time. That way there can be a separate branch for each release’s fixes.
As you presumed, merging takes a lot of time (and also keeping branches synchronized) but you have to lose something to gain something. I worked with the old system (before the feature branches were introduced) and I have to say I like this new one more. Almost every build is usable and I believe that there’s a lot less pressure on developers to finish the features even if they’re running late. Which implicitly also means higher quality.
May I ask you what kind of VC tool you’re using? One SCM tool I’ve fairly recently dealt with is called ‘AllFusion Harvest Change Manager’.
It’s a bit more than just ‘version control’, the ‘repositories’ are losely coupled to the ‘projects’, and each project may have it’s own tasks associated with it. Every task has it’s own files linked to it, which aren’t neccesarily ALL the files from the repository. Tasks can be promoted/demoted from one state in the project to another, eventually ending up with it’s associated files in a ‘view’ of the repository. Such a ‘view’ could be considered a ‘release’. When you check out a release, you will only see the associated files from tasks that have made it to the release view, and consequently, tasks that were not finished in time when the release needs to be pushed out will automatically not be a part of the release.
So the essence of this is the ‘view’ on the repository, and that tasks (call them ‘features’) move independently through the states within a project. If it ain’t there yet, the view won’t see the files associated with that task. If the task is in the view already, we must assume that the code has gone through due process and therefore can be released.
Because of the lose association between project/repository, a new project could use the *same* repository again and tasks that didn’t make it into the release state of the previous project can simply be moved to the new project.
Ofcourse, there’s a price to pay for such functionality as it’s not a free tool like cvs, subversion, git or other tools built on top of them. I’m not an employee of CA, nor do I get percentages from their sales, so this is hardly a commercial 🙂 There are more tools I know of that have similar functionality but Harvest (Nowadays called Software Change Manager) is just the most recent one I used.
I think branch & merge is inherently evil. We never do merges. Ever.
Keep your code in a deployable state by attacking the bug log non-stop.
Do more frequent internal releases of this shipp-able product along with daily builds.
Be very, very conservative in your schedule estimates and don’t commit to a date until you’ve already got the feature (if possible).
Another thing to try is making prototyping risky features a standard part of your software development methodology. That way, you’ll be able to get realistic schedule estimates based on empirical data instead of guessing.
So, my suggestion is to improve your project management and software development methods to fix the problem instead of looking to branch and merge hell to save you.
***Well, my suggestion would be not to make things all too difficult. What we do (using subversion):
Development takes place in the trunk. If one of the developers feels that he/she is working on a complex feature that might not be completed in, say, 4 hours, AND affects other peoples code, a branch is created. This branch is synced with the trunk regularly, to avoid merging hassles later on.
When a releases nears, and not all developers are working on getting the release done, we create a release branch. This means some developers are working in the trunk on new features, others are working in the release branch. This one is also synced regularly, but the other way around. Bugfixes in the release branch are merged in the trunk, to prevent merging conflicts later on.
We don’t create branches if we don’t have to, but we do create them any time we feel our work interferes with other developers, so we never have to delay committing our work to the repository.
Others have already said what I would say, especially about seeking simplicity. But if you’re curious about what other people have done, here’s some interesting reading for you…
YaM is a Perl-based wrapper around CVS (and now SVN) that manages frequent branching and merging, particularly in the context of a large project with several modules being developed rapidly in parallel. It has been used on multiple projects, including the onboard software for JPL’s deep space missions.
The approach they used was to have developers always developing their own software in a “private” branch. With a complex system, that led to the developing of additional tools to manage the complexity.
What we’ve practiced in past with multi-million lines of C code is to have a primary branch A. Draw out another branch B (from A) for an upcoming major release. Thereafter, every engineer (or bug fix) is required to pull out a branch off B, make the fix and hold that branch till its release time.
However, this works well for short cycle releases (typically patches) but, and I totally agree, that involves huge cycles of merging and de-merging, should a roll back was to take place.
If all features/fixes could reside in respective branches pulled out of a mainline and remain there till the moment the release is crystalised (as to what goes and what does not), and then a queue be created for sources to be merged back to the mainline, can possibly handle the situation amicably.
Excessive branching is *evil*. Why? Because sooner or later you will have to do tons of merges. In moderate quantities merges are OK once you have a *good* version control assisted tool for merging.
One way or another, if you have to do merges then the rule of thumb is “Merge Early and Often”.
It is possible to keep a separate branch for each feature, but this is kind of overkill because of the merging volume. You can try to combine this one with change set management. But if a new feature is kept in a set of change sets then it is very likely to have dependencies to other changes not directly related to the feature.
Since branching increases your complexity, you should look to minimize the amount of branching that you do. Not only are merges time consuming, but they can easily introduce problems.
The main problem seems to be that your features are somehow breaking your existing system. You should be trying to design your features to extend the system without breaking backward compatability and therefore until the features are exposed on interfaces (API or GUI) they don’t cause any harm.
For significant new functionality, putting the source into separate directories makes it easy to remove from your build. Obviously some functionality may need to be inserted into other code, but if that is backward compatible and you are avoiding circular dependencies, then it should be safe to leave the hooks even if nothing is ever calling them.
‘ve had success with feature based branching using Accurev.
We were able to support seven distinct features on on the same code base. Prior to Accurev, we had difficulty managing 2 or 3 concurrent development teams.
Basically, according to best practices, release branches and feature branches have quite different purposes.
Release branches are for packages that have been released and shipped already. Ideally the only changes to be committed here are bugfixes and security patches, new features will be developed on the trunk branch.
Feature branches are needed for major code refactoring or for any new feature that is going to take much time to develop and will likely introduce regression bugs or leave the codebase in an inconsistent state. These branches are to be temporary and you will wanto to merge them into the trunk branch as soon as the code becomes stable enough.
For a quite complete discussion of branching and merging you can refer to the Branching chapter of the Subversion book (see website).
From my experience within my organisation and many clients, I’ve seen a lot of different approaches. There isn’t a one strategy fits all with source control. Though keeping it simple is always a good start.
Generally a bit of thought has to go into the architecture of the source to be controlled. I also find that the best fit
a) takes time – so be prepared to inspect and adapt your solution (a little at a time)
b) is a combination of technology, convention and working policy:
from an early stage identify crosscuts of common /shared code and extract that into its own module/project to be controlled – creating a contract between that project and all other projects that depend on it. (in java this would be a jar file that would be the output of any release of the common code, versioned as required.)
create a module for each application and permit only one branch at any one time – this minimises mad merge scenarios.
liberally and routinely use tagging to manage dev releases (perhaps for dev testing), these are great because they allow you to group code/features etc as you like with friendly names, without screwing up your final release. (minor.minor releases)
build, version and release your application (major.major and major.minor) as normal.
you might want to use something like maven or suchlike to manage the project dependencies and assembly.
hope this helps. a little.
*** Sounds like you’ve got more of a design problem on your hands than a version control problem.
The way we handle it is fairly simple. We have one major baseline into which the developers work – features are designed to be modular, that is we can compile them in or out of the code as a whole, or they can be turned on and off via a configuration file.
When a stable version is needed for release, those that pass QA are turned on and compiled in. That then becomes its own branch, with no planned intention on merging it back into the baseline. This allows for minor fixes if needed, but on the whole the next snapshot is important.
When I started (not long ago) we had a setup that needed a lots of merges. At some point it became difficult to manage.
We split the application into small manageable components and changed configuration management in such a way, that I do not remember when is the last time I did a “real” merge… We branch on each major (non-bug-fix) release to be able to support it. We also have the development area separated from integration area. Since the application is split into small chunks, we can simply keep the parts that are not finished from entering the integration.
The team is growing, so you can not tell whether the simple and straightforward current CM will remain that simple in the future, but I am going to have as little branches as possible and as simple merges as possible (if at all) and merge as often as possible 😉