Tutorial :SVN partial branch



Question:

I'm new to SVN so this could be an easy question.

We have a "trunk" with 1st level directories:

10 <-- documents  20 <-- source code, db scripts, ...  30 <-- documents  40 <-- referenced 3rd party library-es  

I made a "develop" branch from the "trunk". In "develop" we change our source code and after testing it we merge it to "trunk".

The problem in that in directories "10" and "30" are stored *.doc files that are not needed for development so it is REQUIRED that "develop" branch doesn't have those directories.

The solution should still:

  1. allow "svn update" on root folder of "develop" working copy, (20 and 40)
  2. that update should not re-create directories 10 and 30 and
  3. of course merging "develop" to "trunk" should NOT delete 10 or 30 in "trunk".

EDIT: I forgot to mention that "source code" is not only in 20. There are referenced dll-s and build scripts etc. that are also on 1st level directory, lets say 40.


Solution:1

If I read your question correctly, this is a simple matter of using svn copy to copy only the desired directories into a branch -- basically, a combination of answers from Mike Kushner and Ivan Krechetov. I think, however, it might be easier to understand after running through the steps yourself, so the rest of this post will create a sample repository and show the copies and merges.

I'm going to assume that you're using the "standard" repository layout, which at the top level has three sub-directories, trunk, branches, and tags. And that your 10, 20, 30, and 40 directories are under trunk. In other words:

trunk      10      20      30      40  branches  tags  

And, as Mike pointed out, your goal will be to have a structure that looks like this:

trunk      10      20      30      40  branches      sandbox          20          40  tags  

It's unclear from your posting (at least as-of the current edit), but you may have a directory structure in which 10, 20, et al are at the top level. In this case, you'll need to create a new top-level directory, which I'll call dev, so that your overall repository looks like the following:

10  20  30  40  dev      20      40  

Note that you cannot create dev under 20. Well, physically you can, but you're almost guaranteed to break your build when doing so.

OK, so let's walk through an example, in which we create a new repository and put some files in it. You have to be able to run the svnadmin command (which you should be able to do, unless you have a paranoid sysadmin). So pick a temporary directory, and execute the following commands (I'm running Linux; if you're running Windows the commands will be the same, but you'll need to put a Windows-specific path in the REPO variable):

svnadmin create temp.repo  REPO="file://`pwd`/temp.repo"  svn co $REPO temp  

This creates a new (empty) repository, and checks out a working copy of it. The second line needs some explanation: it simply creates the repository URL from the current directory. In my workspace directory, the URL looks like this:

file:///home/kgregory/Workspace/temp.repo  

OK, now that you've got a working copy, let's create the sample directory structure and some files:

cd temp  svn mkdir trunk  svn mkdir branches  svn mkdir tags  svn commit -m "standard repo structure"    pushd trunk  svn mkdir 10  svn mkdir 20  svn mkdir 30  svn mkdir 40  svn commit -m "example sub-project structure"    echo "this doesn't change" > 10/dontchange.txt  svn add 10/dontchange.txt  echo "this does change" > 20/change.txt  svn add 20/change.txt  svn status  svn commit -m "example files"  popd  

At this point we have the sample directories and two files in them. Here's the output from find, excluding subversion's hidden directories:

temp, 531> find . | grep -v svn  .  ./tags  ./trunk  ./trunk/10  ./trunk/10/dontchange.txt  ./trunk/30  ./trunk/20  ./trunk/20/change.txt  ./trunk/40  ./branches  

Next step is to create the sandbox directory, and make copies of the two directories that are going to be in it:

svn mkdir branches/sandbox  pushd branches/sandbox  svn copy ${REPO}/trunk/20 .  svn copy ${REPO}/trunk/40 .  svn commit -m "make development branch"  popd  

This is the important part: I creating the branch and copies in my working directory, as a copy from the repository. Normally, you just copy trunk into a child of branches, using svn copy with two repository arguments. That doesn't work here, because we want only two children of trunk.

After doing this, my working copy looks like this:

temp, 539> find . | grep -v svn  .  ./tags  ./trunk  ./trunk/10  ./trunk/10/dontchange.txt  ./trunk/30  ./trunk/20  ./trunk/20/change.txt  ./trunk/40  ./branches  ./branches/sandbox  ./branches/sandbox/20  ./branches/sandbox/20/change.txt  ./branches/sandbox/40  

At this point, you'd normally check out the development branch into a new working directory and work there. So I'll do that (after a cd back to my Workspace directory):

svn co ${REPO}/branches/sandbox sandbox  cd sandbox  

And now make some changes:

vi 20/change.txt  svn commit -m "changed on branch"  

OK, now it's time to merge back to the trunk. So go back to the workspace, and check out just the trunk:

svn co ${REPO}/trunk trunk  cd trunk  

And merge from the sandbox. The merge process is described in the Subversion docs:

svn merge -r 4:5 ${REPO}/branches/sandbox  svn status  

That last command should show you that only the file 20/change.txt was affected by the merge. Since you didn't copy the 10 or 30 directories into the branch, they won't be touched by the merge.


Solution:2

What you want to do is create a copy of "20" somewhere in your svn tree, which you can merge back and forth with. A common structure is

repo  ---> trunk      ---> 10       ---> 20      ---> 30  ---> branches      ---> sandboxes          ---> develop <branch of 20>  ---> tags  

When you want to update "develop", you either create a new branch of "20" under sandboxes or perform a merge from 20 to develop. When you want the changes in "develop" back in your trunk you merge the other way. Your developers should check out a copy of "develop" (or create their own branches based on "develop")


Solution:3

afaik you can't do it with the repository structure you currently have.

I suggest you restructure your repository, so 10 & 20, 40 & the other code related assets are moved under a new 1st level folder. This way you avoid this situation, and simplify being able to grab just the code related assets.


Solution:4

Ideally then you should branch at a lower level. i.e. branch 20 not trunk. That way you're only branching the content that should be branched. i.e. that you want branched.


Solution:5

You can achieve that by making only the source code subdirectory of your working copy point to its branch.

svn cp http://example.com/svnrepo/trunk/source_code http://example.com/svnrepo/branches/development/source_code    cd ./source_code  svn sw http://example.com/svnrepo/branches/development/source_code  

Do the changes, commit. Then, let's merge to the trunk:

svn sw http://example.com/svnrepo/trunk/source_code  cd ..  svn merge -r [start_rev]:HEAD http://example.com/svnrepo/branches/development/source_code ./source_code  

Review to make sure all's fine:

svn diff | less  

And then commit. Done.


Solution:6

We do something like this:

-repo: Assemblies  --SomeAssembly  ---Current  ---v1.0  ---v1.1  -repo: Source  --trunk  ---Code  ---Assemblies (external from Assemblies repo)  --branches  ---v1.0  ----Code  ----Assemblies (external from Assemblies repo)  --Documents  

In this example, the 3rd party assemblies have their own repository. This way you aren't maintaining different versions in each branch and trunk. As a side note, the latest version of any assembly is duplicated in the "Current" folder for each assembly. This allows the assembly to be updated without having to update references in all your projects. This may not be an issue in your domain, but it was a big pain in ours.

Also note that the documents are at the same level in the hierarchy as trunk and the branches. This way those files don't get duplicated. If this is not an option, those can be externaled as well, which would allow them to be present in the trunk and branches without being separately source controlled.


Solution:7

The way you structure your project, along with the docs dir restrictions, doesn't fit with SVN's model out of the box.

Some ideas:

  • Move the docs dir outside trunk, and add it as an svn:external
  • Move the docs dir outside trunk, and have a build script combine trunk and the docs dir
  • Merge using a script (instead of a direct svn merge), and have the script enforce the rules


Solution:8

From your comment:

We want to prevent modification of documents in 10 and 30. They should be modified only in the trunk.

Have you considered using svn:externals in the develop branch for 10 and 30? Relative referencing from root using ^/ would probably be a good approach.

So whilst 10, 20, 30 and 40 would be accessible on the branch, 10 and 30 are still referenced from trunk. You can then define your authorization needs as required.

repo
..-> trunk
....-> 10
....-> 20
....-> 30
....-> 40
..-> branches
....-> develop
......-> 10 (lives on trunk, svn:externals ^/trunk/10)
......-> 20 (lives on branch, merge to trunk)
......-> 30 (lives on trunk, svn:externals ^/trunk/30)
......-> 40 (lives on branch, merge to trunk)


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »