Subversion problems when renaming files and folders

I had an interesting and painful experience with svn. This post is about svn version 1.6.8, I don't know about others. I'd like to share this with the world, but if you don't have the time or patience to read the whole drama, I'll just skip to the moral of the story: if you need to create a patch with changes, do that before you rename files and folders!

My task was to make some changes to files and then to rename these files and their folders. The commit failed, because in the meantime, new versions of the files appeared in the repository.

If a new version is in the repository, you cannot commit your changes automatically. In this case I should update my working copy, but I couldn't, because the names of the folders were changed. Tortoise svn asked if I wanted to merge, but merging trees didn't work. It stopped on merging the renamed file in renamed folder. Then it asked if I wanted to merge that file, but that is a sort of "nested" merge, which didn't succeed, because svn couldn't find previous revision of the file, because it is obviously not (yet) in repository.

I created a patch of changes. I tried reverting the working copy and updating it, then applying the patch, but it didn't work, because it was locked. Svn suggested I do clean, but it didn't change anything. I tried unlocking, but it said nothing is locked. Although "nothing was locked" I still couldn't revert, because it was locked. :|

So I created a fresh (latest) working copy and tried to apply a patch from current one, thus circumventing the failed update and revert processes. Well, that can't be done neither. The patch file is created from comparing base repository and working copy. In my case I modified files and renamed them. Renaming is not an operation in svn, it's done by deleting and adding new file. In patch file this is seen as separate indexes: under old files indexes there is just an instruction to delete them, and all the changes made to file are under the indexes of files with new names.

When I tried to apply such patch to my freshly checked out working copy, it just deleted files with old (original) names, but then couldn't apply the changes to files with new names, because they don't exist in fresh copy. If I manually renamed files in fresh working copy, just so that svn could find them, then it couldn't apply patch because it didn't find previous revision of that file in repository. I can understand why it needs base revision when creating a patch, but why should it need it when applying it? I don't know. Apply of such patch file is therefore impossible whatever you do.

The not so elegant solution, but one that worked for me at the end, is to modify patch file itself:

  1. Edit the patch file and delete all instructions for deleting files with original names.
  2. Modify all sections where it applies diff to a file with new name: change the names of files and folders to old one.
  3. Apply edited patch to fresh (updated!) repository.
  4. Manually, though svn system, rename files and folders. If you don't have a list of renamed files and folders, create one while going through step number 2.
  5. Commit.

What could I have done, if I knew what can go wrong? I could have created a patch before I renamed files and folders. Such patch can still be applied even if everything goes awry, without having to edit (in my case >300kB) large patch file. If the changes do not depend on renamed files, it would also be a good idea to first make changes and commit, then rename files and folders and commit again.

I hope I saved someone a perfectly nice day. :)

Previous: My Unity user experience on Ubuntu 11.04
Next: Collecting screen resolution in web applications