This section is from the "Version Control with Subversion" book, by Ben Collins-Sussman, Brian W. Fitzpatrick and C. Michael Pilato. Also available from Amazon: Version Control with Subversion.
A common desire is to refactor source code, especially in Java-based software projects. Files and directories are shuffled around and renamed, often causing great disruption to everyone working on the project. Sounds like a perfect case to use a branch, doesn't it? Just create a branch, shuffle things around, then merge the branch back to the trunk, right?
Alas, this scenario doesn't work so well right now and is considered one of Subversion's current weak spots. The problem is that Subversion's update command isn't as robust as it should be, particularly when dealing with copy and move operations.
When you use svn copy to duplicate a file, the repository remembers where the new file came from, but it fails to transmit that information to the client which is running svn update or svn merge. Instead of telling the client, “Copy that file you already have to this new location,” it instead sends down an entirely new file. This can lead to problems, especially because the same thing happens with renamed files. A lesser-known fact about Subversion is that it lacks “true renames”—the svn move command is nothing more than an aggregation of svn copy and svn delete.
For example, suppose that while working on your private
branch, you rename integer.c
to whole.c. Effectively you've created
a new file in your branch that is a copy of the original
file, and deleted the original file. Meanwhile, back
on trunk, Sally has committed some
improvements to integer.c. Now you
decide to merge your branch to the trunk:
$ cd calc/trunk
$ svn merge --reintegrate http://svn.example.com/repos/calc/branches/my-calc-branch
D integer.c
A whole.c
This doesn't look so bad at first glance, but it's also
probably not what you or Sally expected. The merge operation
has deleted the latest version of
the integer.c file (the one containing
Sally's latest changes), and blindly added your
new whole.c file—which is a
duplicate of the older version
of integer.c. The net effect is that
merging your “rename” to the branch has removed
Sally's recent changes from the latest revision!
This isn't true data loss; Sally's changes are still in the repository's history, but it may not be immediately obvious that this has happened. The moral of this story is that until Subversion improves, be very careful about merging copies and renames from one branch to another.