tags:

views:

1204

answers:

10

In SVN, trunk is the recommended place for the main development and I use this convention for all of my projects. However, this means that trunk is sometimes unstable, or even broken. This happens for instance when

  • I commit something by mistake
  • When the trunk simply has to be broken because of the way SVN works. Canonical example is file renames - you must commit any file renames first and do any further modifications later; however, file rename may require code refactoring to reflect namespace or class name change so you basically need to commit a single logic operation in two steps. And the build is broken between steps 1 and 2.

I can imagine there would be tools to prevent commiting something by mistake (TeamCity and delayed commits, for instance) but can you really overcome the second problem? If not, wouldn't it be better to do the "wild development" on some branch like /branch/dev and only merge to trunk when the build is reasonably solid?

+23  A: 

Your trunk should ALWAYS compile, if you need to make breaking changes you should use a branch and merge the changes back later.

Read this chapter of the SVN book: http://svnbook.red-bean.com/nightly/en/svn.branchmerge.html

AlbertEin
So you recommend working on trunk and when I need to make a change that requires more SVN commits (like file rename), copy trunk to a short-lived branch, check out that branch, make and commit the changes, and merge them back to trunk? Seems like a pain in the neck but maybe it's the only way...
Borek
Correct. Mainline should always be stable. Risky developments should be done in branches.
David Segonds
My shop's modus operandi is that *all* changes are made in a branch and merged back into the trunk when they are complete. This ensures that even "non-risky" changes do not accidentally break the trunk.
antik
+10  A: 

I would recommend reading this article on SCM best practices.

Extracted from the article:

Have a mainline. A "mainline," or "trunk," is the branch of a codeline that evolves forever. A mainline provides an ultimate destination for almost all changes - both maintenance fixes and new features - and represents the primary, linear evolution of a software product. Release codelines and development codelines are branched from the mainline, and work that occurs in branches is propagated back to the mainline.

Edit: I would also recommend reading SCM Patterns.

David Segonds
+11  A: 

It really depends on your environment. In some cases, having the trunk broken temporarily isn't a big deal. But if you're working with more than 2-3 people, that probably wouldn't be a good idea.

In that case, I'd think using branches more freely is a good idea. They're easy enough to set up, and to remerge (if you don't let things get too far out of sync).

Of course, if all your developers are using the same branch, you won't really gain anything - you'll just have your trunk called /branch/dev, but having it broken would still be a major issue! Break down the branches so that only a few developers work on each one, and you should be good.

zigdon
This has been helpful, thanks.
Borek
As zigdon hints at, in SVN, there is nothing special about trunk (unlike CVS). It's just a folder. That said, I think the concept most people associate with trunk is that it should compile always.
rmeador
+1  A: 

In our company, we have a nightly build of the trunk. It is expected that everybody test their code so that it at the very least compiles before they check it in. If the nightly build fails, the offending code is removed until fixed.

I think the most important part is for everybody to understand the role of subversion and why it is important that they check in only code that compiles.

Fry
A: 
Swanand
it seems like most of development advice runs counter to your release practices.
David Medinets
+5  A: 

The trunk is where the ongoing development is supposed to happen. You really shouldn't have a problem with "broken" code, if everyone is testing their changes before committing them. A good rule of thumb is to do an update (get all the latest code from the repos) after you have coded your changes. Then build and do some unit testing. If everything builds and works, you should be good to check it in.

When you get ready for a release, make a branch. Test can do their release verification against the branch. If problems are found, the fix(s) are made to the branch and trunk, and new cut of the branch is given to test. Meanwhile, the developers are busily adding new changes to the trunk.

So... the issues identified by test and the brilliant solutions to these trivial problems are current in both the branch and trunk, test folk have a stable cut to work with, and development has continued moving forward whilest test verified the current release.

Like Hanibal always said on "The A-Team", "I love it when a plan comes together."

Sunfish
This is exactly what we do. Works great if you don't have too many releases going to Q/A at the same time. If you do, then it's not so great as if something breaks in a previous branch you have to merge back to all more current branches plus the trunk with the fix.
Mat Nadrofsky
+3  A: 

Teams that use Subversion often have a pathological aversion to merging, because prior to 1.5 it was a long complex process prone to failure. If you have enough developers so that having an always working trunk is absolutely necessary since many people are working on many different modules that work together, branchy development will certainly help.

By the way, even when you rename a file you are still permitted to edit it. I do that all the time.

Edward Z. Yang
+1  A: 

I've created a couple of shell-scripts to simplify creating short-lived development branches:

# Create new branch and switch to it
function svn_bswitch()
{
   branch=$1; shift
   msg="$1"; shift

   URL=$(svn info . | sed -ne 's@URL: \(.*\)@\1@p')
   REPO=$(svn info . | sed -ne 's@Repository Root: \(.*\)@\1@p')
   BRANCH_URL=$REPO/branch/$branch

   svn copy $URL $BRANCH_URL -m "$msg"
}


# Switch to a branch or tag
function svn_switch()
{
  d=$1; shift
  REPO=$(svn info . | sed -ne 's@Repository Root: \(.*\)@\1@p')
  URL=$REPO/$d
  svn switch $URL
}
JesperE
+1  A: 

Another example of when the good old "stable trunk, dev in branch" process becomes an issue:

You're developing a web application that depends on a lot of live, possibly user-contributed, data. You can for some reason not just generate another instance of the database backend(-s) or external filesystems that you depend on. (For example, your environment might be lacking data model migrations)

Team A has been developing a new feature F in /branches/F. Team B just started another branch to fix some performance issues that occur on the live site in /branches/P, and the first thing Team B needs to do is refactor a bunch of the database tables and/or how files are laid out on the external filesystem. This causes Team A to have to refactor a lot of their new stuff before they can continue development. Then Team C comes in and does another thing... And suddenly everyone's got an issue.

Then comes the merge phase - and after that nobody ever want's to use TortoiseSVN anymore.

conny
Good point, but this isn't really an SVN issue. How are you expected to do any development without breaking the existing versions? If you don't have a staging or QA version of the DB, then that's the first issue you have to fix.
Outlaw Programmer
I agree. Major breaking changes need the isolation of a source control branch PLUS a separate development environment. In this case, that means a separate database, or at least a separate schema. Typically, I always ensure that everyone can develop in their own complete sandbox.
Rob Williams
A: 

Nope, trunk is not the best place for committing development level code. In our environment, we regard our trunk as the mirror to whatever has been deployed to production. The workflow maybe different for web development and application development but the trunk should contain the latest production changes.

We do work on development branches i.e. branches/feature1 and create a qa tag by copying branches/feature1 --> tags/feature1-qa1 and fix any bugs in branches/feature1 to create tags/feature1-qa1 and so on. When were ready to deploy, all changes that happened in branches/feature1 since last merge to trunk is merged back trunk before creating the final release tag i.e. tags/5.1.0.

Work flow may vary depending on how your team is setup or what type of project/environment you're in.