SVN: Commit replaced directories
Problem
Although there is the Mindquarry Desktop Client, which stores the Subversion metadata (hence the .svn subdirectories) not inside the working directory, I still very much use the standard SVN command line client. Which sometimes brings up the following problem: if a tool replaces an entire directory - examples are Apple Keynote or Eclipse re-compiling code and replacing the classes folder (yes, I know, you shouldn't do it, but sometimes you just have to put it under version control...) - well, if it replaces the directory, the .svn subfolder is lost and you get this ugly status message:
~ subfolder
Which means subversion knows about it (the current folder contains an entry like "directory: subfolder"), but the directory itself is not a working directory (no .svn folder present in subfolder). That status is called "~ replaced"; unfortunately the description in the SVN manual is incomplete: "Item is versioned as a directory, but has been replaced by a file, or vice versa." It should better read: "Item is versioned as a directory, but has been replaced by a file with the same name, or vice versa. It could also indicate that it is versioned as a directory, but has been replaced by a directory of the same name without the important .svn folder inside."
Solution
It's normally a three step process on a standard UNIX command line:
mv subfolder subfolder-temp
svn up subfolder
cp -R subfolder-temp/* subfolder
Note that subfolder-temp is just a temporary name which must not exist yet. The important step is the copy with -R and *, which under UNIX means to copy the tree below subfolder-temp into the existing tree under subfolder. This is technically a simple forward merge. And here is the tricky part: it works for added and modified files, but not for deleted files. You will have to manually delete them. To find out which files are actually deleted, you can use the diff command in recursive and brief mode:
diff -rq subfolder subfolder-temp
For each file it says "Only in subfolder/: foobar", you can delete it:
svn del subfolder/foobar
To make sure everything is correct now, check the status:
svn st subfolder
You should probably also run your (test) code on this "rebuilt" directory or check the files with whatever program is using them. If everything is ok, you can commit it and throw away the temporary copy:
svn ci subfolder
rm -rf subfolder-temp
Quite a long workaround, but somewhat systematic. It's probably possible to write a script that does it, but when I think about it, I would probably never trust the script to not accidentally throw away the local changes ;-).
Update: Martin Probst has such a script (called svnrecover), but it works in a different fashion.
Posted at 12:24PM Apr 16, 2008 by Alexander Klimetschek in General | Comments[2]



I think your solution doesn't solve some problems, namely several nest levels of subfolders. Also, you'll have to manually delete the files that are missing - this can be automated, as in the script.
Posted by Martin Probst on April 16, 2008 at 01:36 PM CEST #
But I posted it step by step to explain the basic concept and to be able to do it by hand if you don't have or don't want a script for that.
And several nested folders are no problem with my solution. I wonder if the script works with deleted files - I can only see that it skips copying for folders that do not exist.... Nevertheless, I will update the entry with the link to your script.
Posted by Alexander Klimetschek on April 16, 2008 at 03:37 PM CEST #