All project content is available for reading, but you need to be a member of the project for Subversion checkout of source code, or to create/modify any information.
Login if you are a member. Apply here to request membership (open to all).

Copy, Move and Rename files and folders in the repository

This How-To explains why it is important to use the Subversion tools to copy, move and rename resources inside the repository. And, not least, why you should NOT just delete and recreate a resource if you want something changed...

What is so important?

First of all, the delete-and-recreate-with-brand-new-copy stragegy should be avoided at all (most) costs... It has a number of disadvantages:

  • History ends: -- Each file and folder in a Subversion repository is a unique resource that is tracked through revisions over time. Here is the key: A new file, with same name, same content, and even recreated in the same location, is NOT identical with the old file - they are totally different as they do not share a history. If you after 6 months work inside a folder accidentially delete it, and then just copy in the folder from a local backup, all your old changeset history will be inacessible.
  • Merging and diff becomes impossible: -- In addition to the fact that 'blame' will not work, and changelog messages are not available, the other side is that comparisons with other 'copies' will not work - be it a copy in another branch or a copy from a previous revision (place or time or both). With no common history, Subversion will always suggest to remove one file and keep the other (full replace).
  • Twice the space: -- Moving or making a copy of an existing resource inside Subversion is effectively only a link that gets updated or added. Making 10 copies (Subversion 'copy') will not increase the size of the repository, and deleting it again is just as easy. A copy made as a file system copy with new commit, will double the size needed. Deleting it again will not change that - it is forever part of the repository as it is a journal archive where ALL information is saved. Large repositories will slow down in use over time, and be more cumbersome to work with.

Copy, Move, Rename

Subversion can have a very distinct use of words at times, talking of 'branching', 'tagging' and so on. Basically they are all just various ways of doing a basic operation: Copy.

  • Branching and Tagging are just direct synonyms for 'copy' - they create a copy of something.
  • A 'Move' is actually two operations internally: It will copy a resource to a new location, and it will delete the reference to the old.
  • A 'Rename' is effectively a 'move' as well, only changing the name on the new resouce that is copied. In fact, it is the same command.

How to do it

Using Subversion Command line

For those using Subversion commandline tools, there are simple operations available that get the job done. Like all Subversion commands, they can be applied to either your working copy or the central repository - or a combination thereof (like grabbing a remote folder as a copy to local working copy).

Running svn help copy will provide plenty help:

copy (cp): Duplicate something in working copy or repository, remembering history.
usage: copy SRC DST

  SRC and DST can each be either a working copy (WC) path or URL:
    WC  -> WC:   copy and schedule for addition (with history)
    WC  -> URL:  immediately commit a copy of WC to URL
    URL -> WC:   check out URL into WC, schedule for addition
    URL -> URL:  complete server-side copy;  used to branch & tag

Valid options:
  -r [--revision] arg      : ARG (some commands also take ARG1:ARG2 range)
                             A revision argument can be one of:
                                NUMBER       revision number
                                '{' DATE '}' revision at start of the date
                                'HEAD'       latest in repository
                                'BASE'       base rev of item's working copy
                                'COMMITTED'  last commit at or before BASE
                                'PREV'       revision just before COMMITTED
  -q [--quiet]             : print as little as possible
  -m [--message] arg       : specify log message ARG
  -F [--file] arg          : read log message from file ARG
  --force-log              : force validity of log message source
  --editor-cmd arg         : use ARG as external editor
  --encoding arg           : treat value as being in charset encoding ARG
  --username arg           : specify a username ARG
  --password arg           : specify a password ARG
  --no-auth-cache          : do not cache authentication tokens
  --non-interactive        : do no interactive prompting
  --config-dir arg         : read user configuration files from directory ARG

Here is illustrations of how to 'tag' a version (an available 'snapshot' of state at some point in time like a version), assuming the whole repository is checked out locally (this example will also rename to a more useful name):

cd c:\svn_projects\my-working-copy\
svn copy trunk tags\version-1.1.3

Another scenario might be that you are working on some changes that turns out to be a bit more complicated or extensive than first planned, and as you do not want to make the trunk unstable, you want to save it to a branch to let the changes get stable there and be reviewed by others before actually merging them back.

# From one level up as a dot (.) for current directory tends to disappear visually in examples:
cd c:\svn_projects\

# Do the copy, and as we are writing to central repos we need a message
svn copy -m "Branching to test new workflow changes." my-working-copy https://www.coderesort.com/svn/sandbox/branches/simon-workflow

# Switch local working copy to point to new branch (copy) instead of trunk for future commits
cd my-working-copy
svn switch https://www.coderesort.com/svn/sandbox/branches/simon-workflow

# Later, changes from the branch can be merged back into trunk when ready
svn commit -m "These changes will go to my new branch, and might make to to trunk eventually." 

The Move and Rename commands follow the same simple pattern: svn move/rename source destination As they are synonyms (it is the same command), the help for both can be listed by svn help move). Read more there if you are unsure.

Using TortoiseSVN

A typical graphical Subversion client will usually only have one mode of operation: Some sort of graphical form that lets you enter do a give command with the values that you want to use - a graphical frontend to the similar command line operation. TortoiseSVN also provides, this, and check the menu for the relevant command - it will operate the same way as described above.

What sets TortoiseSVN above the rest, is the strong Windows Explorer integration. Inside your working copy, if you do 'right-click-and-drag' operations, a special menu appears. Right-dragging a folder from one location to another will make this list appear when you release it:

  • SVN Move versioned files here
  • SVN Move and rename versioned files here
  • SVN Copy versioned files here
  • SVN Copy and rename versioned files here
  • ... and some Add and Export alternatives

The only thing TortoiseSVN will NOT trap is a regular left-click-and-drag, or Explorer Copy & Paste commands - ALWAYS make sure you see some sort of TortoiseSVN window when modifying your working copy through Windows Explorer!

Remember Right-click-and-drag...

Tricks of the trade

Undo an incorrect changeset

If you by accident for instance deleted a folder that should not be deleted, you do not want to recreate it along the lines of the 'do not do this' information above. What you want to do is kind of make it reappear again - the same folder 'undeleted'.

Turns out a neat trick is to use Subversion 'Merge' functionality, and by reversing the order you actually also reverse changes made. Usual use of 'merge' to merge for instance changes in a branch FROM revision 182 TO revision 204 to trunk. Merging by using FROM as a higher number than TO, will ask for the inverse of the changes - and in this example the folder will reappear:

cd c:\svn_projects\my_new_project

# Remove a folder in our project
svn delete my_folder
svn commit -m "Do not need this folder and all these files. Deleting the whole thing."
# Output like:
Deleting my_folder
Committed revision 233.

# Now here is how to undo that change (based on 'svn merge -r from:to source workingcopy').
# Notice that both 'source' (what to compare) and 'workingcopy' (destination) is current directory = . ('dot')
svn merge -r 226:225 . .
# And, ready to commit:
svn commit -m "Ooops. Should not have been deleted, and bringing the folder back from the dead."

For graphical clients that support 'Merge' functionality (like TortoiseSVN), it will work the same - just put the values into the correct fields (reversing from: and to: numbers).

Plan the repository for easy copies

Organise the repository to allow for easy copying of resources (folders especially). If you leave your project files on the root of your repository, making a copy (like a tag) will be cumbersome - and prone to future errors as your /tags folder will be on root and not really distinguishable from the other project resources.

Using the very common /branches /tags and /trunk strategy usually turns out to be a good starting point.