Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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

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.

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

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.

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.

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.

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

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