views:

1352

answers:

9

The subversion concept of branching appears to be focused on creating an [un]stable fork of the entire repository on which to do development. Is there a mechanism for creating branches of individual files?

For a use case, think of a common header (*.h) file that has multiple platform-specific source (*.c) implementations. This type of branch is a permanent one. All of these branches would see ongoing development with occasional cross-branch merging. This is in sharp contrast to unstable development/stable release branches which generally have a finite lifespan.

I do not want to branch the entire repository (cheap or not) as it would create an unreasonable amount of maintenance to continuously merge between the trunk and all the branches. At present I'm using ClearCase, which has a different concept of branching that makes this easy. I've been asked to consider transitioning to SVN but this paradigm difference is important. I'm much more concerned about being able to easily create alternate versions for individual files than about things like cutting a stable release branch.

+2  A: 

A Subversion "branch" is just a copy of something in your repository. So if you wanted to branch a file you'd just do:

svn copy myfile.c myfile_branch.c
Matt
You misunderstand. I want one file with two alternate branches (or "histories" in some other CM systems terminology). I do not want two related but distinct files.
Michael Carman
In Svn, a branch is just a copy (of a file or a directory). So, when branching just one file, you can either keep it in the same directory (but under a different name as suggested here), or put it into a different directory... I doubt that Subversion offers any other options. History is branched.
Alexander
I realize that a branch is just a copy. (SVN's insistence on exposing that in the UI is one of my major gripes with it.) I'm okay with the answer being "you can't do that." I'd rather not use a hammer to drive a screw. I'm just trying to learn what tools are available.
Michael Carman
A: 

A branch in SVN is just a copy. I believe that to do it the way you are hoping to, you'd have to have each version of the file in a separate directory in the repository, and check it out into your source folder. I.E. treat that file like a separate project.

MrZebra
+6  A: 

You don't have to branch the entire repository. You could make branches of folders in your project (such as an include folder). As others have noted, you can also do a "copy" of just a single file. Once you have a copy of a file or folder, you "switch" to the branched file or folder to work on the branch version.

If you create a separate branches folder in the repository, you could copy your branched files there via server side commands:

svn copy svn://server/project/header.h svn://server/branched_files/header.h

Then you could switch that file to use the branches_files repository path

crashmstr
That's rather awkward but could be workable. Thanks for the input.
Michael Carman
+2  A: 

Sadly, I think the real answer here is that ClearCase handles this situation a lot better than Subversion. With subversion, you have to branch everything, but ClearCase allows a kind of "lazy branch" idea that means only a certain group of files are branched, the rest of them still follow the trunk (or whichever branch you specify).

The other solutions provided here don't really work as you intend, they are just copying the file to a different path. Now you have to do odd things to actually use that file.

Erm, sorry. That wasn't really a very good answer. But there isn't a good solution to this with Subversion. Its model is branch and merge.

Edit: OK, so expanding on what crashmstr said. You could do this:

svn cp $REP/trunk/file.h $REP/branched_files/file.h
svn co $REP/trunk
svn switch $REP/branched_files/file.h file.h

But wow!, is that prone to errors. Whenever you do a svn st you will see this:

svn st
    S  file.h

A bit noisy that. And when you want to branch a few files or modules within a large source repository it will start to get very messy.

Actually, there's probably a decent project in here for simulating something like ClearCase's branched files with svn properties and switching, writing a wrapper around the bog standard svn client to deal with all the mess.

rq
+2  A: 

I don't think there is much point in branching a single file? There is no way to test it with the trunk code?

You could take a patch instead if you want to back out changes and apply them later on.

Xian
It's a legitimate task if he has lots of changes to make to that file and wants to be safe yet isolate his teammates from his ongoing work.
Chris Farmer
There is a point. I've updated the question in an attempt to clarify the use case.
Michael Carman
A: 

Are you sure you really need this feature in your VCS ?

Why not use the C preprocessor and #ifdef away the code you don't need ? Or any similar tool.

something like:

// foo.h:
void Foo();

// foo_win32.c
#ifdef _WIN32
void Foo()
{
   ...
}
#endif

// foo_linux.c
#ifdef _GNUC
void Foo()
{
   ...
}
#endif

Sometimes if it doesn't fit right, then it's not the right solution.

rlerallut
Yes, I want this as a feature of the VCS. The use case was just an easy to understand example. My real situation is somewhat more complex and not limited to C. So far "not the right solution" has for me meant not SVN.
Michael Carman
I understand. Good luck !
rlerallut
+2  A: 

Here is how I understand your problem. You have the following tree:

time.h
time.c

and you need to decline it for multiple architectures :

time.h is comon
time.c (for x386), time.c (for ia64), time.c (for alpha),...

Also in your current VCS you can do this by creating as many branches from time.c as needed and when you checkout the files from the VCS you automatically check the latest time.h from the common trunk and the latest time.c from the branch you are working on.

The problem you are concerned about is that if you use SVN when checking out a branch you will have to merge time.h from trunk very often or risk working on an older file (as compared to the trunk) that amount of overhead is not acceptable to you.

Depending on the structure of your source code, there might be a solution though. imagine that you have

 
/
/headers/
/headers/test.h
/source/
/source/test.c

Then you could branch /, and use the svn:externals feature to link your headers to the trunk's head. It only works on directories and bears some limitations with regard to committing back to test.h (you have to go in the header directory for it to work) but it could work.

Jean
A: 

A branch in Subversion is exactly what you are talking about. All of the files are an exact copy of the trunk, with the exception of the ones you change. This is the "cheap copy" methodology talked about in the SVN Book. The only caveat is the need to merge the trunk into the branch from time to time to insure that the changes made there are reflected in the branch. Of course, if those changes are not desired, no trunk->branch merges need to happen.

One easy way to allow for trunk changes to be merged in automatically(which simulates the Clear Case paradigm) would be to use a pre-commit hook script to merge the trunk changes in prior to the commit.(in fact, this is always a good strategy to prevent code drift).

cdeszaq
A: 

Michael and others, did you find a system, preferably GPL, allowing branching individual files? This is needed for development targeting multiple platforms.

Mikael Hakman