tags:

views:

332

answers:

8

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.

A: 

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.

Ivan Krechetov
+2  A: 

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")

mikek
I edited the question. Your solution will not work for us because the "code" is not entirely in 20. Maybe we should restructure things as Freddy Rios suggested. +1 for this would work for unedited question.
Petar Repac
Well then, in that case I'm in agreement with Freddy. Have all your coders check in their stuff and shift it all around so you have it in a manageable structure. Of all the issues you have to handle as CM, this is one of the most basic. And easy to fix :)
mikek
+1  A: 

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.

Michael Wiles
Same comment as for Mike Kushner.
Petar Repac
+2  A: 

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.

eglasius
Nice suggestion. It's an logical option. Will check if management give as a go for restructure (it a company standard so I doubt it).
Petar Repac
Ah, classic situation. Non technical management making technical demands. What you need to do (in my experience, working in a relatively hierarchical but open company) is to create counter demands. Certain things (such as being allowed to restructure the repo) are essential for production, and the advantages of it should surpass those of sticking to the company standard.
mikek
A: 

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.

Daniel Schaffer
+1  A: 

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.

kdgregory
Wow, kdgregory. You have explained this very well and I had a suspension that the solution could be in that direction, but I have little experience with SVN. Tomorrow I'll try this out. Thats a lot.
Petar Repac
I works. Thank you.
Petar Repac
A: 

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
orip
A: 

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)

Si