Question

I have an SVN repository setup, but I have not defined my trunk, and I'm a little confused on how to move code from one branch to another.

The structure is as follows:

--Repo
----Dev
------common
------project
----Test
------common
------project
----Prod
------common
------project

First, which of these should be the trunk? I was thinking the Test branch should be, but the last I ready said the Dev branch should be (although that example only had two branches). Second, all of the code is already in each of the 3 branches, do I need to, and if so, how do I declare one of them as the trunk?

Lastly, when getting ready to promote code to our test branch (which will all be done via Windows explorer, not from a Visual Studio/Xcode project, etc. Do I just click on the branch, do SVN Update, the SVN Merge and select my source to merge from?

Sorry for the newb questions, surprisingly everything I've found on SO is for different scenarios that may/may not apply, I'd just like confirmation to make me feel better so I don't have to redo all of this down the road.

Edit (in reponse to David's answer)

Ok, so I already have the "trunk/branches/tags" beneath the common folder. So I'm guessing I can just remove the Dev/Test/Prod folders altogether (and the contents of prod). The "test" would actually be housed in Repo/foo/branches/test, is that correct? Or I guess it could go Repo/branches/test/foo/, right? (Common is setup as SVN externals...fyi)

Since I haven't used SVN syntax at all, I'll need to go research the --parents thing...We are using Tortoise exclusively, but I guess I'll probably need to learn SVN anyway since this is using Jenkins for the build...

Everything else from your answer looks great! I have only a little Git background, with alot of SourceGear Vault background, so the switchover is still a little confusing.

Was it helpful?

Solution

You don't really need separate code lines for Test, Production, and Development. Unless you expect those in Test and Production to do their own coding. Otherwise, you're going to be copying a lot of stuff back and forth.

The revision the developers are working on (let's say Subversion revision #100) will some time later br taken by the QA team for testing. And, if the QA team likes it, revision #100 will be what gets released into Production. Each team follows the other. Maybe those in development are working on Subversion Revision 100. Meanwhile, QA is testing Revision 97. And, Revision 90 is what is in production. The only thing I would recommend is to tag what goes into production.

Let's take a typical structure:

repo/branches/
repo/tags
repo/trunk/common
repo/trunk/projects

I work off of trunk on project foo. I check out repo/trunk/foo and repo/trunk/common do my work and check in my changes.

Now, let's say I want tag Revision 90 off my trunk because that's been approved for production, I can tag my release like this:

$ svn cp --parents -r 90 $REPO/trunk/foo@90 $REPO/tags/1.3/foo
$ svn cp -r 90 $REPO/trunk/common@90 $REPO/tags/1.3/common

If I need to see what was release, I can check out the 1.3 release tag from my repository.

There are two ways you normally use branching:

  • You branch on release.
  • You branch on feature.

I'm going to describe release branching because it's just easier.

Imagine you're working on your 1.3 release. At some point, some of your developers have no more work to do on your 1.3 release, and want to work on release 1.4.

Up to this point, the work for your 1.3 release was being done on trunk. Your 1.4 developers can't do their work because they don't want to make 1.4 changes while you're working on 1.3 code changes. So, they sit around all day playing Candy Crush until 1.3 is complete, and everyone can work off of trunk on release 1.4.

In order to cut down on the Candy Crunch time, I'm going to make a release branch:

$ svn cp --parents $REPO/trunk/foo $REPO/branches/1.3/foo
$ svn cp $REPO/trunk/common $REPO/branches/1.3/common

Now, those developers still working on release 1.3 switch their working copies to the 1.3 branch while those working on 1.4 remain working on the trunk. Once your release is complete, you can tag it right off the branch:

$ svn cp --parents $REPO/branches/1.3/foo $REPO/tags/1.3/foo
$ svn cp $REPO/branches/1.3/commons $REPO/tags/1.3/commons

When Release 1.4 approaches, you rinse and repeat.

$ svn cp --parents $REPO/trunk/foo $REPO/branches/1.4/foo
$ svn cp $REPO/trunk/common $REPO/branches/1.4/common

Now, those working on Release 1.5 continue working on trunk while those working on Release 1.4 work off the branch.

What if you need to make a hot fix? Say there's a bug in Release 1.4? You already have a 1.4 branch which I assume was no longer used when Release 1.4 came out (It's easy enough to check. Compare the latest revision on the 1.4 branch with the revision that made the 1.4 tag). Just do your work for Release 1.4.1 on the 1.4 branch.

As you see, it's not all that complicated. By the way, there's no reason you can't reverse the names too:

$REPO/foo/trunk
$REPO/foo/branches
$REPO/foo/tags

$REPO/common/trunk
$REPO/common/branches
$REPO/common/tags

In this case, I'm treating each project as a separate sub-depository with its own branching and tagging. I might want to do this if all of my projects are on different release schedules.


Response

Ok, so I already have the "trunk/branches/tags" beneath the common folder. So I'm guessing I can just remove the Dev/Test/Prod folders altogether (and the contents of prod). The "test" would actually be housed in Repo/foo/branches/test, is that correct? Or I guess it could go Repo/branches/test/foo/, right? (Common is setup as SVN externals...fyi)

There's no need for a test branch. QA simply tests a particular Subversion release right off the branch that the developers are using. For example, let's say that Subversion is on Revision 100 and QA is testing Revision 95. If QA finds a bug, it gets reported and incorporated into Revision 101. When QA tests Revision 101 or higher, they can test to see if that bug has been fixed. If it has, they can close out the bug. Otherwise, they may reopen it.

If you use a Continuous Integration System like Jenkins which builds your software with every change, you might be talking about a particular build. The last build will be Build #30, but QA is testing Build #28. If QA find a bug, development will simply fix it and Jenkins will produce Build #31. QA can then test Build #31 to see if the bug has been fixed.

We used Jira and Jenkins in one shop, and these were integrated. When a developer fixed a bug, they would put that bug number into the commit message. Jenkins would then update that Jira ticket with the Jenkins build. If QA finds a fixed issue, they could look at the Jira ticket, see the Jenkins build where it was fixed and test it.

I hope this makes sense and why you don't need branches for test, production, etc.

Since I haven't used SVN syntax at all, I'll need to go research the --parents thing...We are using Tortoise exclusively, but I guess I'll probably need to learn SVN anyway since this is using Jenkins for the build...

It's always good to know the command line version of the Subversion client. Sometimes, when things go wrong in TortoiseSVN, you can get more information from the command line client to see what's going on. The --parents parameter merely means to create parent directories that may or may not be there. For example, you want to create the directory /branches/4.3/foo, but there might not be a /branches/4.3 directory. In TortoiseSVN, I believe this would be created automatically. In the command line client, the --parents parameter would create both the /branches/4.3 directory (if it doesn't exist) and the /branches/4.3/foo directory too.

Everything else from your answer looks great! I have only a little Git background, with alot of SourceGear Vault background, so the switchover is still a little confusing.

Subversion is actually pretty simple when compared to Git since there's only one level of repository. You checkout, modify, commit.

The big difference between Git and SVN is that SVN is linear. Revision 100 is always before Revision 101. In Git, revisions have no real order. The repository revisions are represented as blobs with checksums. The order is imposed by trees that point to particular blobs. However, it's probably harder for someone who's familiar with SVN to understand Git than the other way around.

Wait, one more question, how would I automate the build for my test environment if the branch name is going to change every release (ie 1.3, 1.4, etc)?

In Jenkins, we simply have a bunch of shell scripts that duplicate the projects. I've setup the projects, so the change between them is minimal: I merely change the branch names. Run my script, and presto, more Jenkins jobs are created. Run another, and the old branch jobs are deleted.

Some sites use a post-commit trigger to build a Jenkins job that takes place on a branch. In Jenkins, you can pass a parameter to the build, so you pass the branch where the change took place, and Jenkins builds on that branch. As they move from one release to another, they never have to create new jobs.

Now, if you do releases on a weekly or fortnightly basis, you might not need release branches. Everything is off of trunk (except for the occasional hot patches). In this case, it's very likely that everyone in your team is working on the same release. I branch in order to allow two different groups of developers to work on Release 1.3 and 1.4 (which is on trunk) at the same time. If you don't have that issue, there's no need for a release branch (except for the occasional hot fix).

OTHER TIPS

the trunk/tags/branches is just naming convention. I would suggest you Dev on the trunk, Then Merge to Test when preparing to release. For clarity sake you can rename your Dev branch to 'trunk' so you don't get confused co-developers.

The Prod branch seems a bit overkill; you can tag versions in your Test branch which have gone to production.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top