[svn] How do I return to an older version of our code in Subversion?

I'm working on a project with a friend and I want to return to an older version of our code and set it to be the current. How do I do it?

I'm using "anksvn" on vs08.

I have the version that I want on my PC, but the commit is failing; The message that I get is "commit is failed, file or directory is out of date."

I also have the subversion client on my PC.

This question is related to svn backport

The answer is


There are a lot of dangerous answers on this page. Note that since SVN version 1.6, doing an update -r can cause tree conflicts, which rapidly escalates into a potentially data losing kafkeresque nightmare where you're googling for information on tree conflicts.

The correct way to revert to a version is:

svn merge -r HEAD:12345 .

Where 12345 is the version number. Don't forget the dot.


Just use this line

svn update -r yourOldRevesion

You can know your current revision by using:

svn info


Right-click on the highest hierarchy you want to revert >> Revert or Revert to Revision


You can only commit new changes at the head of the subversion history.

The reason you can't do anything directly with the good copy you have on your PC, is that its .svn folders know that it is code from the past, so requires an update before any commit.

Find the good revision number and revert

  1. Find the revision number of the old copy you want.

    Get your current revision with:

    svn info --show-item revision
    # or
    svn log
    

    Or to check older versions of your project, use:

    svn update -r <earlier_revision_number>
    

    until you find the right revision number.

  2. Note down the good revision number (assuming 123 for examples below).

  3. Update to the latest revision:

    svn update
    
  4. Undo all the changes between the revision you want and the latest version:

    svn merge -r HEAD:123 .
    svn commit "Reverted to revision 123"
    

    (the same as Jon Skeet's answer above.)

If you can't find the revision number

If you can't find the old copy, and you just want to commit the files currently on your PC:

  1. Make a copy of your good version (but without any .svn folders):

    cd ..
    rsync -ai --exclude=.svn  project/  project-good/
    
  2. Now make sure you have the latest version:

    cd project
    svn update
    # or make a fresh checkout
    svn checkout <url>
    
  3. Copy your good version over the top of the working copy.

    This command will copy, and also delete any files from the working tree that aren't in your good copy, but it won't affect the existing .svn folders.

    cd ..
    rsync -ai --exclude=.svn --delete  project-good/  project/
    

    If you don't have rsync, you can use cp -a but you will also need to delete any unwanted files manually.

  4. You should be able to commit what you have now.

    cd project
    svn commit "Reverted to good copy"
    

The following has worked for me.

I had a lot of local changes and needed to discard those in the local copy and checkout the last stable version in SVN.

  1. Check the status of all files, including the ignored files.

  2. Grep all the lines to get the newly added and ignored files.

  3. Replace those with //.

  4. and rm -rf all the lines.

    svn status --no-ignore | grep '^[?I]' | sed "s/^[?I] //" | xargs -I{} rm -rf "{}"


Jon Skeet's answer is pretty much the solution in a nutshell, however if you are like me, you might want an explanation. The Subversion manual calls this a

Cherry-Pick Merge

From the man pages.

  1. This form is called a 'cherry-pick' merge: '-r N:M' refers to the difference in the history of the source branch between revisions N and M.

    A 'reverse range' can be used to undo changes. For example, when source and target refer to the same branch, a previously committed revision can be 'undone'. In a reverse range, N is greater than M in '-r N:M', or the '-c' option is used with a negative number: '-c -M' is equivalent to '-r M:'. Undoing changes like this is also known as performing a 'reverse merge'.


  • If the source is a file, then differences are applied to that file (useful for reverse-merging earlier changes). Otherwise, if the source is a directory, then the target defaults to '.'.

    In normal usage the working copy should be up to date, at a single revision, with no local modifications and no switched subtrees.

Example:

svn merge -r 2983:289 path/to/file

This will replace the local copy[2983] (which, according to the quote above, should be in sync with the server--your responsibility) with the revision 289 from the server. The change happens locally, which means if you have a clean checkout, then the changes can be inspected before committing them.


Sync to the older version and commit it. This should do the trick.

Here's also an explanation of undoing changes.


I think this is most suited:

Do the merging backward, for instance, if the committed code contains the revision from rev 5612 to 5616, just merge it backwards. It works in my end.

For instance:

svn merge -r 5616:5612 https://<your_svn_repository>/

It would contain a merged code back to former revision, then you could commit it.


This is what I did and worked for me.

I want to undo the changes in multiple commits that I did for certain times and want to go to the previous commit point.

  1. Go to Team -> Show History.
  2. Right-click on the or range of revisions you want to ignore.
  3. Select the "Revert changes" option.

This will run a reverse merge, undoing the changes in your working copy.

Just review the code and commit.


A bit more old-school

svn diff -r 150:140 > ../r140.patch
patch -p0 < ../r140.patch

then the usual

svn diff
svn commit

The standard way of using merge to undo the entire check-in works great, if that's what you want to do. Sometimes, though, all you want to do is revert a single file. There's no legitimate way to do that, but there is a hack:

  1. Find the version that you want using svn log.
  2. Use svn's export subcommand:

    svn export http://url-to-your-file@123 /tmp/filename

(Where 123 is the revision number for a good version of the file.) Then either move or copy that single file to overwrite the old one. Check in the modified file and you are done.


Most of the previous answers have been using a reverse merge, and that's usually the right answer. However, there's one situation (which just happened to me) where it's not.

I accidentally changed a file with Unix line endings to DOS line endings when making a small change, and committed it. This is easily undone, either by changing the line endings and committing again, or by a reverse merge, but it has the effect of making svn blame list my edit as the source of every line of the file. (Interestingly, TortoiseSVN on Windows doesn't get affected by this; only the command line svn blame.)

If you want to maintain the history as reported by svn blame, I think you need to do the following:

  • Delete the file and commit.
  • In the repository, copy the previous good copy of the file into the head, and commit.
  • Restore any edits that you do want to keep.

The deletion is a little scary, but remember you always have the file saved in the repository, so restoring it is not a big deal. Here's some code to illustrate the steps. Assume that xxx is the revision number of the last good copy.

svn rm svn+ssh://path/to/file
svn copy svn+ssh://path/to/file@xxx svn+ssh://path/to -m"Restore good copy"
svn update
<restore the edits>
svn commit -m"Restore edits"

Note that for a copy in the repository, the destination needs to be a directory, not a filename.


Right click the project > Replace With > Revision or URL > Select the specific revision you want to revert.

Now commit the local update code version to the repository. This will revert the code base to the specific revision.