views:

282

answers:

6

In the project that I'm working on, we are using SVN with 'Stable Trunk' strategy. What that means is that for each bug that is found, QA opens a bug ticket and assigns it to a developer. Then, a developer fixes that bug and checks it in a branch (off trunk, let's call this the bug branch) and that branch will only contain fixes for that particular bug ticket

When we decided to do a release, for each bug fixes that we want to release to the customer, a developer will merge all the fixes from several bug branch to trunk and proceed with the normal QA cycle.

The problem is that we use trunk as the codebase for our CI job (Hudson, specifically), and therefore, for all commits to the bug branch, it will miss the daily build until it gets merged to trunk when we decided to release the new version of the software. Obviously, that defeats the purpose of having CI.

What is the proper way to fix this issue?

A: 

Instead of creating branches for your bug fixes, why don't you try creating branches for the version before the bug fix, and then apply the fix to the trunk.

This way, if you want to give your customers the bug fix, you give them the trunk version. If you do not want to give them the bug fix, you can give them the branch version before your fix was applied.

This way, you can have Hudson build the trunk line, and your nightly builds will include all your bug fixes.

Sagar
A: 

Do a nightly merge to an "unstable-evil-twin-trunk" that merges all bug branches to the evil-twin-trunk.

Or set up nightly builds on each bug-branch (which sounds like a lot of nightly builds).

In my opinion, this sounds like an awful lot of branching for a centralized style source control solution. Maybe you need a distributed version control system and a build server on each workstation, which it seems would accomplish the same thing (isolated check ins for each developer and daily builds on what the developers check in)

MatthewMartin
+6  A: 

As you note, one purpose of using a branch is to segregate specific code fluctuations from ticket-fixing and feature development away from the trunk. But once the feature or ticket is complete, you should merge it back. In Subversion, branches are better used to track sets of related features (like those for a release), not individual features. Otherwise you will quickly wind up with unmanageable numbers of branches.

Furthermore, why delay the integration at all? The longer you wait between releases, the higher the likelihood that your isolated change will conflict with another change made since then and/or produce further instability in your system once merged back.

My preferred strategy is to do something like this:

    [begin work on 0.4 branch]
       |
       |
       v              
(*)---(*)-------(a)--(b)---(c)-- <-- Trunk is "unstable".
         \       |          |        Contains all commits.
    ver   \   [merge from trunk]     Developers commit to trunk.
<-- 0.3    \     v          v
            +---(a)--------(c)-- <-- Branch is "stable".
                                     Contains selected commits from trunk.
                                     Know beforehand what's going onto branch.

Now, once you're ready for release:

[trunk]
(*)---(*)---(*)----------------------------[development continues]--->


[0.4 branch]                        No further development on branch unless
(*)---(*)---(*)---[0.4-release]     spot fixes are needed. Then re-tag (0.4.1)
                          ^         and re-release.
                          |         
                          |
                       [make tag on branch; release from stable branch,
                        not unstable trunk]

I know you asked about the best way to coerce your continuous integration system to do this. But I would respectfully suggest that given that Hudson is recognized as a relatively capable CI system, the fact that you're having a lot of trouble shoehorning your development model into it is a possible sign that it's not a process that lends itself well to CI in the first place.

Our typical practice is to have two base builds per project: one against trunk and one against the current release branch. This way you know that:

  • Whatever is being updated is being integrated correctly (trunk)
  • Whatever your release target is, if you stopped working now you would still have a correct and working (just not fully featured) build.
John Feminella
+1  A: 

That sounds painful and overly complicated (from a branch/merge standpoint).

I would branch at release and have developers check in to the trunk. Anything that needs to go out as a hot fix could be merged with the release branch.

Chuck
A: 

I answer this a lot, and here's how IBM recommends it with ClearCase (UCM), and I do it in the real world:

 - Project
    |-  development mainline 
    |-  TAG: version-1.0 
         |- version-1.0-bugfix#123 
         |- version-1.0-bugfixes 
    |-  TAG: version-1.0-sp1 
         |- version-1.0-sp1-bugfix#234 
         |- version-1.0.sp1-bugfixes 
    |-  TAG: version-1.0-sp2 

Anything not prefixed by TAG is a branch.

Chris Kaminski
Can you explain how this solves the problem? I don't quite understand.
ryanprayogo
You need to set up CI on your development mainline, and your version-1.0-bugfixes branch. Periodically, when you want to promote version-1.0-bugfixes to a release, you'll create a tag called version-1.0-sp# This way you're only dealing with 1+(n*versions) branches, instead of 1+(n*versions)*X branches
Chris Kaminski
+1  A: 

Here is what we do (inspired from Version Control for Multiple Agile Teams by Henrik Kniberg):

  • development is done in a development branch and features are pushed to trunk when "done done"
  • trunk is the "done" branch
  • at release time, we tag the trunk
  • when a defect comes up, we create a release branch from the tag
  • defects is patched in the release branch
  • patch is merged from release branch to trunk immediately after releasing (to include it in future releases)

alt text

CI runs on all branches (development branches, trunk, release branches).

Pascal Thivent
So what does your CI system build from ?
gareth_bowles
@gareth_bowles Hmm... what? I wrote that the CI runs on development branches, on the trunk, on release branches (each having more strict rules than the previous one). What is not clear?
Pascal Thivent
Doh - sorry, I missed your last sentence.
gareth_bowles