An extremely common use for svn merge
is to roll back a change that has already been committed.
Suppose you’re working away happily on a working copy of /calc/trunk, and you discover that the change
made way back in revision 303, which changed integer.c, is completely wrong. It never
should have been committed. You can use svn merge to “undo” the
change in your working copy, and then commit the local modification to
the repository. All you need to do is to specify a
reverse difference. (You can do this by specifying
--revision 303:302
, or by an equivalent
--change -303
.)
$ svn merge -c -303 http://svn.example.com/repos/calc/trunk --- Reverse-merging r303 into 'integer.c': U integer.c $ svn status M . M integer.c $ svn diff ... # verify that the change is removed ... $ svn commit -m "Undoing change committed in r303." Sending integer.c Transmitting file data . Committed revision 350.
As we mentioned earlier, one way to think about a repository
revision is as a specific changeset. By using the -r
option, you can ask svn merge to
apply a changeset, or a whole range of changesets, to your working copy.
In our case of undoing a change, we’re asking svn merge to apply changeset #303 to our
working copy backward.
Keep in mind that rolling back a change like this is just like any
other svn merge operation, so you
should use svn status and svn diff to confirm that your work is in the
state you want it to be in, and then use svn
commit to send the final version to the repository. After
committing, this particular changeset is no longer reflected in the
HEAD
revision.
Again, you may be thinking: well, that really didn’t undo the commit, did it? The change still exists in revision 303. If somebody checks out a version of the calc project between revisions 303 and 349, she’ll still see the bad change, right?
Yes, that’s true. When we talk about “removing” a
change, we’re really talking about removing it from the HEAD
revision. The original change still
exists in the repository’s history. For most situations, this is good
enough. Most people are only interested in tracking the HEAD
of a project anyway. There are special
cases, however, where you really might want to destroy all evidence of
the commit. (Perhaps somebody accidentally committed a confidential
document.) This isn’t so easy, it turns out, because Subversion was
deliberately designed to never lose information. Revisions are immutable
trees that build upon one another. Removing a revision from history
would cause a domino effect, creating chaos in all subsequent revisions
and possibly invalidating all working copies.[21]
[21] The Subversion project has plans, however, to someday implement a command that would accomplish the task of permanently deleting information. In the meantime, see svndumpfilter for a possible workaround.