TortoiseSVN

A Subversion client for Windows

Version 1.6.99

Stefan Küng

Lübbe Onken

Simon Large

2010/02/01 01:02:41 (r18483)


Table of Contents

Preface
Audience
Reading Guide
TortoiseSVN is free!
Community
Acknowledgments
Terminology used in this document
1. Introduction
What is TortoiseSVN?
TortoiseSVN's History
TortoiseSVN's Features
Installing TortoiseSVN
System requirements
Installation
Language Packs
Spellchecker
2. Basic Version-Control Concepts
The Repository
Versioning Models
The Problem of File-Sharing
The Lock-Modify-Unlock Solution
The Copy-Modify-Merge Solution
What does Subversion Do?
Subversion in Action
Working Copies
Repository URLs
Revisions
How Working Copies Track the Repository
Summary
3. The Repository
Repository Creation
Creating a Repository with the Command Line Client
Creating The Repository With TortoiseSVN
Local Access to the Repository
Accessing a Repository on a Network Share
Repository Layout
Repository Backup
Server side hook scripts
Checkout Links
Accessing the Repository
Svnserve Based Server
Introduction
Installing svnserve
Running svnserve
Basic Authentication with svnserve
Better Security with SASL
Authentication with svn+ssh
Path-based Authorization with svnserve
Apache Based Server
Introduction
Installing Apache
Installing Subversion
Configuration
Multiple Repositories
Path-Based Authorization
Authentication With a Windows Domain
Multiple Authentication Sources
Securing the server with SSL
Using client certificates with virtual SSL hosts
4. Daily Use Guide
Getting Started
Icon Overlays
Context Menus
Drag and Drop
Common Shortcuts
Authentication
Maximizing Windows
Importing Data Into A Repository
Import
Import in Place
Special Files
Checking Out A Working Copy
Checkout Depth
Committing Your Changes To The Repository
The Commit Dialog
Change Lists
Excluding Items from the Commit List
Commit Log Messages
Commit Progress
Update Your Working Copy With Changes From Others
Resolving Conflicts
File Conflicts
Tree Conflicts
Getting Status Information
Icon Overlays
TortoiseSVN Columns In Windows Explorer
Local and Remote Status
Viewing Diffs
Change Lists
Revision Log Dialog
Invoking the Revision Log Dialog
Revision Log Actions
Getting Additional Information
Getting more log messages
Current Working Copy Revision
Merge Tracking Features
Changing the Log Message and Author
Filtering Log Messages
Statistical Information
Offline Mode
Refreshing the View
Viewing Differences
File Differences
Line-end and Whitespace Options
Comparing Folders
Diffing Images Using TortoiseIDiff
External Diff/Merge Tools
Adding New Files And Directories
Copying/Moving/Renaming Files and Folders
Ignoring Files And Directories
Pattern Matching in Ignore Lists
Deleting, Moving and Renaming
Deleting files and folders
Moving files and folders
Changing case in a filename
Dealing with filename case conflicts
Repairing File Renames
Deleting Unversioned Files
Undo Changes
Cleanup
Project Settings
Subversion Properties
TortoiseSVN Project Properties
External Items
External Folders
External Files
Branching / Tagging
Creating a Branch or Tag
Other ways to create a branch or tag
To Checkout or to Switch...
Merging
Merging a Range of Revisions
Reintegrate a branch
Merging Two Different Trees
Merge Options
Reviewing the Merge Results
Merge Tracking
Handling Conflicts during Merge
Merge a Completed Branch
Feature Branch Maintenance
Locking
How Locking Works in Subversion
Getting a Lock
Releasing a Lock
Checking Lock Status
Making Non-locked Files Read-Only
The Locking Hook Scripts
Creating and Applying Patches
Creating a Patch File
Applying a Patch File
Who Changed Which Line?
Blame for Files
Blame Differences
The Repository Browser
Revision Graphs
Revision Graph Nodes
Changing the View
Using the Graph
Refreshing the View
Pruning Trees
Exporting a Subversion Working Copy
Removing a working copy from version control
Relocating a working copy
Integration with Bug Tracking Systems / Issue Trackers
Adding Issue Numbers to Log Messages
Getting Information from the Issue Tracker
Integration with Web-based Repository Viewers
TortoiseSVN's Settings
General Settings
Revision Graph Settings
Icon Overlay Settings
Network Settings
External Program Settings
Saved Data Settings
Log Caching
Client Side Hook Scripts
TortoiseBlame Settings
Subversion Working Folders
Advanced Settings
Final Step
5. The SubWCRev Program
The SubWCRev Command Line
Keyword Substitution
Keyword Example
COM interface
6. IBugtraqProvider interface
The IBugtraqProvider interface
The IBugtraqProvider2 interface
A. Frequently Asked Questions (FAQ)
B. How Do I...
Move/copy a lot of files at once
Force users to enter a log message
Hook-script on the server
Project properties
Update selected files from the repository
Roll back (Undo) revisions in the repository
Use the revision log dialog
Use the merge dialog
Use svndumpfilter
Compare two revisions of a file or folder
Include a common sub-project
Use svn:externals
Use a nested working copy
Use a relative location
Create a shortcut to a repository
Ignore files which are already versioned
Unversion a working copy
Remove a working copy
C. Useful Tips For Administrators
Deploy TortoiseSVN via group policies
Redirect the upgrade check
Setting the SVN_ASP_DOT_NET_HACK environment variable
Disable context menu entries
D. Automating TortoiseSVN
TortoiseSVN Commands
Tsvncmd URL handler
TortoiseIDiff Commands
E. Command Line Interface Cross Reference
Conventions and Basic Rules
TortoiseSVN Commands
Checkout
Update
Update to Revision
Commit
Diff
Show Log
Check for Modifications
Revision Graph
Repo Browser
Edit Conflicts
Resolved
Rename
Delete
Revert
Cleanup
Get Lock
Release Lock
Branch/Tag
Switch
Merge
Export
Relocate
Create Repository Here
Add
Import
Blame
Add to Ignore List
Create Patch
Apply Patch
F. Implementation Details
Icon Overlays
G. Securing Svnserve using SSH
Setting Up a Linux Server
Setting Up a Windows Server
SSH Client Tools for use with TortoiseSVN
Creating OpenSSH Certificates
Create Keys using ssh-keygen
Create Keys using PuTTYgen
Test using PuTTY
Testing SSH with TortoiseSVN
SSH Configuration Variants
Glossary
Index

List of Figures

2.1. A Typical Client/Server System
2.2. The Problem to Avoid
2.3. The Lock-Modify-Unlock Solution
2.4. The Copy-Modify-Merge Solution
2.5. ...Copy-Modify-Merge Continued
2.6. The Repository's Filesystem
2.7. The Repository
3.1. The TortoiseSVN menu for unversioned folders
4.1. Explorer showing icon overlays
4.2. Context menu for a directory under version control
4.3. Explorer file menu for a shortcut in a versioned folder
4.4. Right drag menu for a directory under version control
4.5. Authentication Dialog
4.6. The Import dialog
4.7. The Checkout dialog
4.8. The Commit dialog
4.9. The Commit Dialog Spellchecker
4.10. The Progress dialog showing a commit in progress
4.11. Progress dialog showing finished update
4.12. Explorer showing icon overlays
4.13. Check for Modifications
4.14. Commit dialog with Changelists
4.15. The Revision Log Dialog
4.16. The Revision Log Dialog Top Pane with Context Menu
4.17. Top Pane Context Menu for 2 Selected Revisions
4.18. The Log Dialog Bottom Pane with Context Menu
4.19. The Log Dialog Showing Merge Tracking Revisions
4.20. Commits-by-Author Histogram
4.21. Commits-by-Author Pie Chart
4.22. Commits-by-date Graph
4.23. Go Offline Dialog
4.24. The Compare Revisions Dialog
4.25. The image difference viewer
4.26. Explorer context menu for unversioned files
4.27. Right drag menu for a directory under version control
4.28. Explorer context menu for unversioned files
4.29. Explorer context menu for versioned files
4.30. Revert dialog
4.31. Explorer property page, Subversion tab
4.32. Subversion property page
4.33. Adding properties
4.34. The Branch/Tag Dialog
4.35. The Switch Dialog
4.36. The Merge Wizard - Select Revision Range
4.37. The Merge Wizard - Reintegrate Merge
4.38. The Merge Wizard - Tree Merge
4.39. The Merge Conflict Callback Dialog
4.40. The Merge reintegrate Dialog
4.41. The Locking Dialog
4.42. The Check for Modifications Dialog
4.43. The Create Patch dialog
4.44. The Annotate / Blame Dialog
4.45. TortoiseBlame
4.46. The Repository Browser
4.47. A Revision Graph
4.48. The Export-from-URL Dialog
4.49. The Relocate Dialog
4.50. Example issue tracker query dialog
4.51. The Settings Dialog, General Page
4.52. The Settings Dialog, Context Menu Page
4.53. The Settings Dialog, Dialogs 1 Page
4.54. The Settings Dialog, Dialogs 2 Page
4.55. The Settings Dialog, Colours Page
4.56. The Settings Dialog, Revision Graph Page
4.57. The Settings Dialog, Revision Graph Colors Page
4.58. The Settings Dialog, Icon Overlays Page
4.59. The Settings Dialog, Icon Set Page
4.60. The Settings Dialog, Network Page
4.61. The Settings Dialog, Diff Viewer Page
4.62. The Settings Dialog, Diff/Merge Advanced Dialog
4.63. The Settings Dialog, Saved Data Page
4.64. The Settings Dialog, Log Cache Page
4.65. The Settings Dialog, Log Cache Statistics
4.66. The Settings Dialog, Hook Scripts Page
4.67. The Settings Dialog, Configure Hook Scripts
4.68. The Settings Dialog, Issue Tracker Integration Page
4.69. The Settings Dialog, TortoiseBlame Page
C.1. The upgrade dialog

List of Tables

2.1. Repository Access URLs
3.1. Apache httpd.conf Settings
5.1. List of available command line switches
5.2. List of available command line switches
5.3. COM/automation methods supported
C.1. Menu entries and their values
D.1. List of available commands and options
D.2. List of available options

Preface

  • Do you work in a team?

  • Has it ever happened that you were working on a file, and someone else was working on the same file at the same time? Did you lose your changes to that file because of that?

  • Have you ever saved a file, and then wanted to revert the changes you made? Have you ever wished you could see what a file looked like some time ago?

  • Have you ever found a bug in your project and wanted to know when that bug got into your files?

If you answered “yes” to one of these questions, then TortoiseSVN is for you! Just read on to find out how TortoiseSVN can help you in your work. It's not that difficult.

Audience

This book is written for computer literate folk who want to use Subversion to manage their data, but are uncomfortable using the command line client to do so. Since TortoiseSVN is a windows shell extension it's assumed that the user is familiar with the windows explorer and knows how to use it.

Reading Guide

This Preface explains a little about the TortoiseSVN project, the community of people who work on it, and the licensing conditions for using it and distributing it.

The Chapter 1, Introduction explains what TortoiseSVN is, what it does, where it comes from and the basics for installing it on your PC.

In Chapter 2, Basic Version-Control Concepts we give a short introduction to the Subversion revision control system which underlies TortoiseSVN. This is borrowed from the documentation for the Subversion project and explains the different approaches to version control, and how Subversion works.

The chapter on Chapter 3, The Repository explains how to set up a local repository, which is useful for testing Subversion and TortoiseSVN using a single PC. It also explains a bit about repository administration which is also relevant to repositories located on a server. There is also a section here on how to setup a server if you need one.

The Chapter 4, Daily Use Guide is the most important section as it explains all the main features of TortoiseSVN and how to use them. It takes the form of a tutorial, starting with checking out a working copy, modifying it, committing your changes, etc. It then progresses to more advanced topics.

Chapter 5, The SubWCRev Program is a separate program included with TortoiseSVN which can extract the information from your working copy and write it into a file. This is useful for including build information in your projects.

The Appendix B, How Do I... section answers some common questions about performing tasks which are not explicitly covered elsewhere.

The section on Appendix D, Automating TortoiseSVN shows how the TortoiseSVN GUI dialogs can be called from the command line. This is useful for scripting where you still need user interaction.

The Appendix E, Command Line Interface Cross Reference give a correlation between TortoiseSVN commands and their equivalents in the Subversion command line client svn.exe.

TortoiseSVN is free!

TortoiseSVN is free. You don't have to pay to use it, and you can use it any way you want. It is developed under the GNU General Public License (GPL).

TortoiseSVN is an Open Source project. That means you have full read access to the source code of this program. You can browse it on this link http://tortoisesvn.tigris.org/svn/tortoisesvn/ . You will be prompted to enter username and password. The username is guest, and the password must be left blank. The most recent version (where we're currently working) is located under /trunk/, and the released versions are located under /tags/.

Community

Both TortoiseSVN and Subversion are developed by a community of people who are working on those projects. They come from different countries all over the world and work together to create wonderful programs.

Acknowledgments

Tim Kemp

for founding the TortoiseSVN project

Stefan Küng

for the hard work to get TortoiseSVN to what it is now

Lübbe Onken

for the beautiful icons, logo, bug hunting, translating and managing the translations

Simon Large

for helping with the documentation and bug hunting

The Subversion Book

for the great introduction to Subversion and its chapter 2 which we copied here

The Tigris Style project

for some of the styles which are reused in this documentation

Our Contributors

for the patches, bug reports and new ideas, and for helping others by answering questions on our mailing list.

Our Donators

for many hours of joy with the music they sent us

Terminology used in this document

To make reading the docs easier, the names of all the screens and Menus from TortoiseSVN are marked up in a different font. The Log Dialog for instance.

A menu choice is indicated with an arrow. TortoiseSVNShow Log means: select Show Log from the TortoiseSVN context menu.

Where a local context menu appears within one of the TortoiseSVN dialogs, it is shown like this: Context MenuSave As ...

User Interface Buttons are indicated like this: Press OK to continue.

User Actions are indicated using a bold font. Alt+A: press the Alt-Key on your keyboard and while holding it down press the A-Key as well. Right-drag: press the right mouse button and while holding it down drag the items to the new location.

System output and keyboard input is indicated with a different font as well.

Important

Important notes are marked with an icon.

Tip

Tips that make your life easier.

Caution

Places where you have to be careful what you are doing.

Warning

Where extreme care has to be taken, data corruption or other nasty things may occur if these warnings are ignored.

Chapter 1. Introduction

Version control is the art of managing changes to information. It has long been a critical tool for programmers, who typically spend their time making small changes to software and then undoing or checking some of those changes the next day. Imagine a team of such developers working concurrently - and perhaps even simultaneously on the very same files! - and you can see why a good system is needed to manage the potential chaos.

What is TortoiseSVN?

TortoiseSVN is a free open-source client for the Subversion version control system. That is, TortoiseSVN manages files and directories over time. Files are stored in a central repository. The repository is much like an ordinary file server, except that it remembers every change ever made to your files and directories. This allows you to recover older versions of your files and examine the history of how and when your data changed, and who changed it. This is why many people think of Subversion and version control systems in general as a sort of “time machine”.

Some version control systems are also software configuration management (SCM) systems. These systems are specifically tailored to manage trees of source code, and have many features that are specific to software development - such as natively understanding programming languages, or supplying tools for building software. Subversion, however, is not one of these systems; it is a general system that can be used to manage any collection of files, including source code.

TortoiseSVN's History

In 2002, Tim Kemp found that Subversion was a very good version control system, but it lacked a good GUI client. The idea for a Subversion client as a Windows shell integration was inspired by the similar client for CVS named TortoiseCVS.

Tim studied the source code of TortoiseCVS and used it as a base for TortoiseSVN. He then started the project, registered the domain tortoisesvn.org and put the source code online. During that time, Stefan Küng was looking for a good and free version control system and found Subversion and the source for TortoiseSVN. Since TortoiseSVN was still not ready for use then he joined the project and started programming. Soon he rewrote most of the existing code and started adding commands and features, up to a point where nothing of the original code remained.

As Subversion became more stable it attracted more and more users who also started using TortoiseSVN as their Subversion client. The user base grew quickly (and is still growing every day). That's when Lübbe Onken offered to help out with some nice icons and a logo for TortoiseSVN. And he takes care of the website and manages the translation.

TortoiseSVN's Features

What makes TortoiseSVN such a good Subversion client? Here's a short list of features.

Shell integration

TortoiseSVN integrates seamlessly into the Windows shell (i.e. the explorer). This means you can keep working with the tools you're already familiar with. And you do not have to change into a different application each time you need functions of the version control!

And you are not even forced to use the Windows Explorer. TortoiseSVN's context menus work in many other file managers, and in the File/Open dialog which is common to most standard Windows applications. You should, however, bear in mind that TortoiseSVN is intentionally developed as extension for the Windows Explorer. Thus it is possible that in other applications the integration is not as complete and e.g. the icon overlays may not be shown.

Icon overlays

The status of every versioned file and folder is indicated by small overlay icons. That way you can see right away what the status of your working copy is.

Easy access to Subversion commands

All Subversion commands are available from the explorer context menu. TortoiseSVN adds its own submenu there.

Since TortoiseSVN is a Subversion client, we would also like to show you some of the features of Subversion itself:

Directory versioning

CVS only tracks the history of individual files, but Subversion implements a “virtual” versioned filesystem that tracks changes to whole directory trees over time. Files and directories are versioned. As a result, there are real client-side move and copy commands that operate on files and directories.

Atomic commits

A commit either goes into the repository completely, or not at all. This allows developers to construct and commit changes as logical chunks.

Versioned metadata

Each file and directory has an invisible set of “properties” attached. You can invent and store any arbitrary key/value pairs you wish. Properties are versioned over time, just like file contents.

Choice of network layers

Subversion has an abstracted notion of repository access, making it easy for people to implement new network mechanisms. Subversion's “advanced” network server is a module for the Apache web server, which speaks a variant of HTTP called WebDAV/DeltaV. This gives Subversion a big advantage in stability and interoperability, and provides various key features for free: authentication, authorization, wire compression, and repository browsing, for example. A smaller, standalone Subversion server process is also available. This server speaks a custom protocol which can be easily tunneled over ssh.

Consistent data handling

Subversion expresses file differences using a binary differencing algorithm, which works identically on both text (human-readable) and binary (human-unreadable) files. Both types of files are stored equally compressed in the repository, and differences are transmitted in both directions across the network.

Efficient branching and tagging

The cost of branching and tagging need not be proportional to the project size. Subversion creates branches and tags by simply copying the project, using a mechanism similar to a hard-link. Thus these operations take only a very small, constant amount of time, and very little space in the repository.

Hackability

Subversion has no historical baggage; it is implemented as a collection of shared C libraries with well-defined APIs. This makes Subversion extremely maintainable and usable by other applications and languages.

Installing TortoiseSVN

System requirements

TortoiseSVN runs on Windows 2000 SP2, Windows XP or higher. Windows 98, Windows ME and Windows NT4 are no longer supported since TortoiseSVN 1.2.0, but you can still download the older versions if you really need them.

If you encounter any problems during or after installing TortoiseSVN please refer to Appendix A, Frequently Asked Questions (FAQ) first.

Installation

TortoiseSVN comes with an easy to use installer. Double click on the installer file and follow the instructions. The installer will take care of the rest.

Important

You need Administrator privileges to install TortoiseSVN.

Language Packs

The TortoiseSVN user interface has been translated into many different languages, so you may be able to download a language pack to suit your needs. You can find the language packs on our translation status page . And if there is no language pack available yet, why not join the team and submit your own translation ;-)

Each language pack is packaged as a .exe installer. Just run the install program and follow the instructions. Next time you restart, the translation will be available.

Spellchecker

TortoiseSVN includes a spell checker which allows you to check your commit log messages. This is especially useful if the project language is not your native language. The spell checker uses the same dictionary files as OpenOffice and Mozilla .

The installer automatically adds the US and UK English dictionaries. If you want other languages, the easiest option is simply to install one of TortoiseSVN's language packs. This will install the appropriate dictionary files as well as the TortoiseSVN local user interface. Next time you restart, the dictionary will be available too.

Or you can install the dictionaries yourself. If you have OpenOffice or Mozilla installed, you can copy those dictionaries, which are located in the installation folders for those applications. Otherwise, you need to download the required dictionary files from http://wiki.services.openoffice.org/wiki/Dictionaries

Once you have got the dictionary files, you probably need to rename them so that the filenames only have the locale chars in it. Example:

  • en_US.aff

  • en_US.dic

Then just copy them to the bin sub-folder of the TortoiseSVN installation folder. Normally this will be C:\Program Files\TortoiseSVN\bin. If you don't want to litter the bin sub-folder, you can instead place your spell checker files in C:\Program Files\TortoiseSVN\Languages. If that folder isn't there, you have to create it first. The next time you start TortoiseSVN, the spell checker will be available.

If you install multiple dictionaries, TortoiseSVN uses these rules to select which one to use.

  1. Check the tsvn:projectlanguage setting. Refer to the section called “Project Settings” for information about setting project properties.

  2. If no project language is set, or that language is not installed, try the language corresponding to the Windows locale.

  3. If the exact Windows locale doesn't work, try the “Base” language, eg. de_CH (Swiss-German) falls back to de_DE (German).

  4. If none of the above works, then the default language is English, which is included with the standard installation.

Chapter 2. Basic Version-Control Concepts

This chapter is a slightly modified version of the same chapter in the Subversion book. An online version of the Subversion book is available here: http://svnbook.red-bean.com/ .

This chapter is a short, casual introduction to Subversion. If you're new to version control, this chapter is definitely for you. We begin with a discussion of general version control concepts, work our way into the specific ideas behind Subversion, and show some simple examples of Subversion in use.

Even though the examples in this chapter show people sharing collections of program source code, keep in mind that Subversion can manage any sort of file collection - it's not limited to helping computer programmers.

The Repository

Subversion is a centralized system for sharing information. At its core is a repository, which is a central store of data. The repository stores information in the form of a filesystem tree - a typical hierarchy of files and directories. Any number of clients connect to the repository, and then read or write to these files. By writing data, a client makes the information available to others; by reading data, the client receives information from others.

Figure 2.1. A Typical Client/Server System

A Typical Client/Server System

So why is this interesting? So far, this sounds like the definition of a typical file server. And indeed, the repository is a kind of file server, but it's not your usual breed. What makes the Subversion repository special is that it remembers every change ever written to it: every change to every file, and even changes to the directory tree itself, such as the addition, deletion, and rearrangement of files and directories.

When a client reads data from the repository, it normally sees only the latest version of the filesystem tree. But the client also has the ability to view previous states of the filesystem. For example, a client can ask historical questions like, “what did this directory contain last Wednesday?”, or “who was the last person to change this file, and what changes did they make?” These are the sorts of questions that are at the heart of any version control system: systems that are designed to record and track changes to data over time.

Versioning Models

All version control systems have to solve the same fundamental problem: how will the system allow users to share information, but prevent them from accidentally stepping on each other's feet? It's all too easy for users to accidentally overwrite each other's changes in the repository.

The Problem of File-Sharing

Consider this scenario: suppose we have two co-workers, Harry and Sally. They each decide to edit the same repository file at the same time. If Harry saves his changes to the repository first, then it's possible that (a few moments later) Sally could accidentally overwrite them with her own new version of the file. While Harry's version of the file won't be lost forever (because the system remembers every change), any changes Harry made won't be present in Sally's newer version of the file, because she never saw Harry's changes to begin with. Harry's work is still effectively lost - or at least missing from the latest version of the file - and probably by accident. This is definitely a situation we want to avoid!

Figure 2.2. The Problem to Avoid

The Problem to Avoid

The Lock-Modify-Unlock Solution

Many version control systems use a lock-modify-unlock model to address this problem, which is a very simple solution. In such a system, the repository allows only one person to change a file at a time. First Harry must lock the file before he can begin making changes to it. Locking a file is a lot like borrowing a book from the library; if Harry has locked a file, then Sally cannot make any changes to it. If she tries to lock the file, the repository will deny the request. All she can do is read the file, and wait for Harry to finish his changes and release his lock. After Harry unlocks the file, his turn is over, and now Sally can take her turn by locking and editing.

Figure 2.3. The Lock-Modify-Unlock Solution

The Lock-Modify-Unlock Solution

The problem with the lock-modify-unlock model is that it's a bit restrictive, and often becomes a roadblock for users:

  • Locking may cause administrative problems. Sometimes Harry will lock a file and then forget about it. Meanwhile, because Sally is still waiting to edit the file, her hands are tied. And then Harry goes on vacation. Now Sally has to get an administrator to release Harry's lock. The situation ends up causing a lot of unnecessary delay and wasted time.

  • Locking may cause unnecessary serialization. What if Harry is editing the beginning of a text file, and Sally simply wants to edit the end of the same file? These changes don't overlap at all. They could easily edit the file simultaneously, and no great harm would come, assuming the changes were properly merged together. There's no need for them to take turns in this situation.

  • Locking may create a false sense of security. Pretend that Harry locks and edits file A, while Sally simultaneously locks and edits file B. But suppose that A and B depend on one another, and the changes made to each are semantically incompatible. Suddenly A and B don't work together anymore. The locking system was powerless to prevent the problem - yet it somehow provided a sense of false security. It's easy for Harry and Sally to imagine that by locking files, each is beginning a safe, insulated task, and thus inhibits them from discussing their incompatible changes early on.

The Copy-Modify-Merge Solution

Subversion, CVS, and other version control systems use a copy-modify-merge model as an alternative to locking. In this model, each user's client reads the repository and creates a personal working copy of the file or project. Users then work in parallel, modifying their private copies. Finally, the private copies are merged together into a new, final version. The version control system often assists with the merging, but ultimately a human being is responsible for making it happen correctly.

Here's an example. Say that Harry and Sally each create working copies of the same project, copied from the repository. They work concurrently, and make changes to the same file A within their copies. Sally saves her changes to the repository first. When Harry attempts to save his changes later, the repository informs him that his file A is out-of-date. In other words, that file A in the repository has somehow changed since he last copied it. So Harry asks his client to merge any new changes from the repository into his working copy of file A. Chances are that Sally's changes don't overlap with his own; so once he has both sets of changes integrated, he saves his working copy back to the repository.

Figure 2.4. The Copy-Modify-Merge Solution

The Copy-Modify-Merge Solution

Figure 2.5. ...Copy-Modify-Merge Continued

...Copy-Modify-Merge Continued

But what if Sally's changes do overlap with Harry's changes? What then? This situation is called a conflict, and it's usually not much of a problem. When Harry asks his client to merge the latest repository changes into his working copy, his copy of file A is somehow flagged as being in a state of conflict: he'll be able to see both sets of conflicting changes, and manually choose between them. Note that software can't automatically resolve conflicts; only humans are capable of understanding and making the necessary intelligent choices. Once Harry has manually resolved the overlapping changes (perhaps by discussing the conflict with Sally!), he can safely save the merged file back to the repository.

The copy-modify-merge model may sound a bit chaotic, but in practice, it runs extremely smoothly. Users can work in parallel, never waiting for one another. When they work on the same files, it turns out that most of their concurrent changes don't overlap at all; conflicts are infrequent. And the amount of time it takes to resolve conflicts is far less than the time lost by a locking system.

In the end, it all comes down to one critical factor: user communication. When users communicate poorly, both syntactic and semantic conflicts increase. No system can force users to communicate perfectly, and no system can detect semantic conflicts. So there's no point in being lulled into a false promise that a locking system will somehow prevent conflicts; in practice, locking seems to inhibit productivity more than anything else.

There is one common situation where the lock-modify-unlock model comes out better, and that is where you have unmergeable files. For example if your repository contains some graphic images, and two people change the image at the same time, there is no way for those changes to be merged together. Either Harry or Sally will lose their changes.

What does Subversion Do?

Subversion uses the copy-modify-merge solution by default, and in many cases this is all you will ever need. However, as of Version 1.2, Subversion also supports file locking, so if you have unmergeable files, or if you are simply forced into a locking policy by management, Subversion will still provide the features you need.

Subversion in Action

Working Copies

You've already read about working copies; now we'll demonstrate how the Subversion client creates and uses them.

A Subversion working copy is an ordinary directory tree on your local system, containing a collection of files. You can edit these files however you wish, and if they're source code files, you can compile your program from them in the usual way. Your working copy is your own private work area: Subversion will never incorporate other people's changes, nor make your own changes available to others, until you explicitly tell it to do so.

After you've made some changes to the files in your working copy and verified that they work properly, Subversion provides you with commands to publish your changes to the other people working with you on your project (by writing to the repository). If other people publish their own changes, Subversion provides you with commands to merge those changes into your working directory (by reading from the repository).

A working copy also contains some extra files, created and maintained by Subversion, to help it carry out these commands. In particular, each directory in your working copy contains a subdirectory named .svn, also known as the working copy administrative directory. The files in each administrative directory help Subversion recognize which files contain unpublished changes, and which files are out-of-date with respect to others' work.

A typical Subversion repository often holds the files (or source code) for several projects; usually, each project is a subdirectory in the repository's filesystem tree. In this arrangement, a user's working copy will usually correspond to a particular subtree of the repository.

For example, suppose you have a repository that contains two software projects.

Figure 2.6. The Repository's Filesystem

The Repository's Filesystem

In other words, the repository's root directory has two subdirectories: paint and calc.

To get a working copy, you must check out some subtree of the repository. (The term check out may sound like it has something to do with locking or reserving resources, but it doesn't; it simply creates a private copy of the project for you).

Suppose you make changes to button.c. Since the .svn directory remembers the file's modification date and original contents, Subversion can tell that you've changed the file. However, Subversion does not make your changes public until you explicitly tell it to. The act of publishing your changes is more commonly known as committing (or checking in) changes to the repository.

To publish your changes to others, you can use Subversion's commit command.

Now your changes to button.c have been committed to the repository; if another user checks out a working copy of /calc, they will see your changes in the latest version of the file.

Suppose you have a collaborator, Sally, who checked out a working copy of /calc at the same time you did. When you commit your change to button.c, Sally's working copy is left unchanged; Subversion only modifies working copies at the user's request.

To bring her project up to date, Sally can ask Subversion to update her working copy, by using the Subversion update command. This will incorporate your changes into her working copy, as well as any others that have been committed since she checked it out.

Note that Sally didn't need to specify which files to update; Subversion uses the information in the .svn directory, and further information in the repository, to decide which files need to be brought up to date.

Repository URLs

Subversion repositories can be accessed through many different methods - on local disk, or through various network protocols. A repository location, however, is always a URL. The URL schema indicates the access method:

Table 2.1. Repository Access URLs

SchemaAccess Method
file:// Direct repository access on local or network drive.
http:// Access via WebDAV protocol to Subversion-aware Apache server.
https:// Same as http://, but with SSL encryption.
svn:// Unauthenticated TCP/IP access via custom protocol to a svnserve server.
svn+ssh:// authenticated, encrypted TCP/IP access via custom protocol to a svnserve server.

For the most part, Subversion's URLs use the standard syntax, allowing for server names and port numbers to be specified as part of the URL. The file:// access method is normally used for local access, although it can be used with UNC paths to a networked host. The URL therefore takes the form file://hostname/path/to/repos. For the local machine, the hostname portion of the URL is required to be either absent or localhost. For this reason, local paths normally appear with three slashes, file:///path/to/repos.

Also, users of the file:// scheme on Windows platforms will need to use an unofficially “standard” syntax for accessing repositories that are on the same machine, but on a different drive than the client's current working drive. Either of the two following URL path syntaxes will work where X is the drive on which the repository resides:

file:///X:/path/to/repos
...
file:///X|/path/to/repos
...

Note that a URL uses ordinary slashes even though the native (non-URL) form of a path on Windows uses backslashes.

You can safely access a FSFS repository via a network share, but you cannot access a BDB repository in this way.

Warning

Do not create or access a Berkeley DB repository on a network share. It cannot exist on a remote filesystem. Not even if you have the network drive mapped to a drive letter. If you attempt to use Berkeley DB on a network share, the results are unpredictable - you may see mysterious errors right away, or it may be months before you discover that your repository database is subtly corrupted.

Revisions

A svn commit operation can publish changes to any number of files and directories as a single atomic transaction. In your working copy, you can change files' contents, create, delete, rename and copy files and directories, and then commit the complete set of changes as a unit.

In the repository, each commit is treated as an atomic transaction: either all the commits changes take place, or none of them take place. Subversion retains this atomicity in the face of program crashes, system crashes, network problems, and other users' actions.

Each time the repository accepts a commit, this creates a new state of the filesystem tree, called a revision. Each revision is assigned a unique natural number, one greater than the number of the previous revision. The initial revision of a freshly created repository is numbered zero, and consists of nothing but an empty root directory.

A nice way to visualize the repository is as a series of trees. Imagine an array of revision numbers, starting at 0, stretching from left to right. Each revision number has a filesystem tree hanging below it, and each tree is a “snapshot” of the way the repository looked after each commit.

Figure 2.7. The Repository

The Repository

It's important to note that working copies do not always correspond to any single revision in the repository; they may contain files from several different revisions. For example, suppose you check out a working copy from a repository whose most recent revision is 4:

calc/Makefile:4
     integer.c:4
     button.c:4

At the moment, this working directory corresponds exactly to revision 4 in the repository. However, suppose you make a change to button.c, and commit that change. Assuming no other commits have taken place, your commit will create revision 5 of the repository, and your working copy will now look like this:

calc/Makefile:4
     integer.c:4
     button.c:5

Suppose that, at this point, Sally commits a change to integer.c, creating revision 6. If you use svn update to bring your working copy up to date, then it will look like this:

calc/Makefile:6
     integer.c:6
     button.c:6

Sally's changes to integer.c will appear in your working copy, and your change will still be present in button.c. In this example, the text of Makefile is identical in revisions 4, 5, and 6, but Subversion will mark your working copy of Makefile with revision 6 to indicate that it is still current. So, after you do a clean update at the top of your working copy, it will generally correspond to exactly one revision in the repository.

How Working Copies Track the Repository

For each file in a working directory, Subversion records two essential pieces of information in the .svn/ administrative area:

  • what revision your working file is based on (this is called the file's working revision), and

  • a timestamp recording when the local copy was last updated by the repository.

Given this information, by talking to the repository, Subversion can tell which of the following four states a working file is in:

Unchanged, and current

The file is unchanged in the working directory, and no changes to that file have been committed to the repository since its working revision. A commit of the file will do nothing, and an update of the file will do nothing.

Locally changed, and current

The file has been changed in the working directory, and no changes to that file have been committed to the repository since its base revision. There are local changes that have not been committed to the repository, thus a commit of the file will succeed in publishing your changes, and an update of the file will do nothing.

Unchanged, and out-of-date

The file has not been changed in the working directory, but it has been changed in the repository. The file should eventually be updated, to make it current with the public revision. A commit of the file will do nothing, and an update of the file will fold the latest changes into your working copy.

Locally changed, and out-of-date

The file has been changed both in the working directory, and in the repository. A commit of the file will fail with an out-of-date error. The file should be updated first; an update command will attempt to merge the public changes with the local changes. If Subversion can't complete the merge in a plausible way automatically, it leaves it to the user to resolve the conflict.

Summary

We've covered a number of fundamental Subversion concepts in this chapter:

  • We've introduced the notions of the central repository, the client working copy, and the array of repository revision trees.

  • We've seen some simple examples of how two collaborators can use Subversion to publish and receive changes from one another, using the 'copy-modify-merge' model.

  • We've talked a bit about the way Subversion tracks and manages information in a working copy.

Chapter 3. The Repository

No matter which protocol you use to access your repositories, you always need to create at least one repository. This can either be done with the Subversion command line client or with TortoiseSVN.

If you haven't created a Subversion repository yet, it's time to do that now.

Repository Creation

You can create a repository with the FSFS backend or with the older Berkeley Database (BDB) format. The FSFS format is generally faster and easier to administer, and it works on network shares and Windows 98 without problems. The BDB format was once considered more stable simply because it has been in use for longer, but since FSFS has now been in use in the field for several years, that argument is now rather weak. Read Choosing a Data Store in the Subversion book for more information.

Creating a Repository with the Command Line Client

  1. Create an empty folder with the name SVN (e.g. D:\SVN\), which is used as root for all your repositories.

  2. Create another folder MyNewRepository inside D:\SVN\.

  3. Open the command prompt (or DOS-Box), change into D:\SVN\ and type

    svnadmin create --fs-type bdb MyNewRepository
    

    or

    svnadmin create --fs-type fsfs MyNewRepository
    

Now you've got a new repository located at D:\SVN\MyNewRepository.

Creating The Repository With TortoiseSVN

Figure 3.1. The TortoiseSVN menu for unversioned folders

The TortoiseSVN menu for unversioned folders

  1. Open the windows explorer

  2. Create a new folder and name it e.g. SVNRepository

  3. Right-click on the newly created folder and select TortoiseSVNCreate Repository here....

    A repository is then created inside the new folder. Don't edit those files yourself!!!. If you get any errors make sure that the folder is empty and not write protected.

Tip

TortoiseSVN no longer offers the option to create BDB repositories, although you can still use the command line client to create them. FSFS repositories are generally easier for you to maintain, and also makes it easier for us to maintain TortoiseSVN due to compatibility issues between the different BDB versions.

Future versions of TortoiseSVN will not support file:// access to BDB repositories due to these compatibility issues, although it will of course always support this repository format when accessed via a server through the svn://, http:// or https:// protocols. For this reason, we strongly recommend that any new repository which must be accessed using file:// protocol is created as FSFS.

Of course we also recommend that you don't use file:// access at all, apart from local testing purposes. Using a server is more secure and more reliable for all but single-developer use.

Local Access to the Repository

To access your local repository you need the path to that folder. Just remember that Subversion expects all repository paths in the form file:///C:/SVNRepository/. Note the use of forward slashes throughout.

To access a repository located on a network share you can either use drive mapping, or you can use the UNC path. For UNC paths, the form is file://ServerName/path/to/repos/. Note that there are only 2 leading slashes here.

Prior to SVN 1.2, UNC paths had to be given in the more obscure form file:///\ServerName/path/to/repos. This form is still supported, but not recommended.

Warning

Do not create or access a Berkeley DB repository on a network share. It cannot exist on a remote file system. Not even if you have the network drive mapped to a drive letter. If you attempt to use Berkeley DB on a network share, the results are unpredictable - you may see mysterious errors right away, or it may be months before you discover that your repository database is subtly corrupted.

Accessing a Repository on a Network Share

Although in theory it is possible to put a FSFS repository on a network share and have multiple users access it using file:// protocol, this is most definitely not recommended. In fact we would strongly discourage it, and do not support such use.

Firstly you are giving every user direct write access to the repository, so any user could accidentally delete the entire repository or make it unusable in some other way.

Secondly not all network file sharing protocols support the locking that Subversion requires, so you may find your repository gets corrupted. It may not happen straight away, but one day two users will try to access the repository at the same time.

Thirdly the file permissions have to be set just so. You may just about get away with it on a native Windows share, but SAMBA is particularly difficult.

file:// access is intended for local, single-user access only, particularly testing and debugging. When you want to share the repository you really need to set up a proper server, and it is not nearly as difficult as you might think. Read the section called “Accessing the Repository” for guidelines on choosing and setting up a server.

Repository Layout

Before you import your data into the repository you should first think about how you want to organize your data. If you use one of the recommended layouts you will later have it much easier.

There are some standard, recommended ways to organize a repository. Most people create a trunk directory to hold the “main line” of development, a branches directory to contain branch copies, and a tags directory to contain tag copies. If a repository holds only one project, then often people create these top-level directories:

/trunk
/branches
/tags

If a repository contains multiple projects, people often index their layout by branch:

/trunk/paint
/trunk/calc
/branches/paint
/branches/calc
/tags/paint
/tags/calc

...or by project:

/paint/trunk
/paint/branches
/paint/tags
/calc/trunk
/calc/branches
/calc/tags

Indexing by project makes sense if the projects are not closely related and each one is checked out individually. For related projects where you may want to check out all projects in one go, or where the projects are all tied together in a single distribution package, it is often better to index by branch. This way you have only one trunk to checkout, and the relationships between the sub-projects is more easily visible.

If you adopt a top level /trunk /tags /branches approach, there is nothing to say that you have to copy the entire trunk for every branch and tag, and in some ways this structure offers the most flexibility.

For unrelated projects you may prefer to use separate repositories. When you commit changes, it is the revision number of the whole repository which changes, not the revision number of the project. Having 2 unrelated projects share a repository can mean large gaps in the revision numbers. The Subversion and TortoiseSVN projects appear at the same host address, but are completely separate repositories allowing independent development, and no confusion over build numbers.

Of course, you're free to ignore these common layouts. You can create any sort of variation, whatever works best for you or your team. Remember that whatever you choose, it's not a permanent commitment. You can reorganize your repository at any time. Because branches and tags are ordinary directories, TortoiseSVN can move or rename them however you wish.

Switching from one layout to another is just a matter of issuing a series of server-side moves; If you don't like the way things are organized in the repository, just juggle the directories around.

So if you haven't already created a basic folder structure inside your repository you should do that now. There are two ways to achieve this. If you simply want to create a /trunk /tags /branches structure, you can use the repository browser to create the three folders (in three separate commits). If you want to create a deeper hierarchy then it is simpler to create a folder structure on disk first and import it in a single commit, like this:

  1. create a new empty folder on your hard drive

  2. create your desired top-level folder structure inside that folder - don't put any files in it yet!

  3. import this structure into the repository via a right click on the folder and selecting TortoiseSVNImport... This will import your temp folder into the repository root to create the basic repository layout.

Note that the name of the folder you are importing does not appear in the repository, only its contents. For example, create the following folder structure:

C:\Temp\New\trunk
C:\Temp\New\branches
C:\Temp\New\tags

Import C:\Temp\New into the repository root, which will then look like this:

/trunk
/branches
/tags

Repository Backup

Whichever type of repository you use, it is vitally important that you maintain regular backups, and that you verify the backup. If the server fails, you may be able to access a recent version of your files, but without the repository all your history is lost forever.

The simplest (but not recommended) way is just to copy the repository folder onto the backup medium. However, you have to be absolutely sure that no process is accessing the data. In this context, access means any access at all. A BDB repository is written to even when the operation only appears to require reading, such as getting status. If your repository is accessed at all during the copy, (web browser left open, WebSVN, etc.) the backup will be worthless.

The recommended method is to run

svnadmin hotcopy path/to/repository path/to/backup --clean-logs

to create a copy of your repository in a safe manner. Then backup the copy. The --clean-logs option is not required, but removes any redundant log files when you backup a BDB repository, which may save some space.

The svnadmin tool is installed automatically when you install the Subversion command line client. If you are installing the command line tools on a Windows PC, the best way is to download the Windows installer version. It is compressed more efficiently than the .zip version, so the download is smaller, and it takes care of setting the paths for you. You can download the latest version of the Subversion command line client from http://subversion.apache.org/getting.html .

Server side hook scripts

A hook script is a program triggered by some repository event, such as the creation of a new revision or the modification of an unversioned property. Each hook is handed enough information to tell what that event is, what target(s) it's operating on, and the username of the person who triggered the event. Depending on the hook's output or return status, the hook program may continue the action, stop it, or suspend it in some way. Please refer to the chapter on Hook Scripts in the Subversion Book for full details about the hooks which are implemented.

These hook scripts are executed by the server that hosts the repository. TortoiseSVN also allows you to configure client side hook scripts that are executed locally upon certain events. See the section called “Client Side Hook Scripts” for more information.

Sample hook scripts can be found in the hooks directory of the repository. These sample scripts are suitable for Unix/Linux servers but need to be modified if your server is Windows based. The hook can be a batch file or an executable. The sample below shows a batch file which might be used to implement a pre-revprop-change hook.

rem Only allow log messages to be changed.
if "%4" == "svn:log" exit 0
echo Property '%4' cannot be changed >&2
exit 1

Note that anything sent to stdout is discarded. if you want a message to appear in the Commit Reject dialog you must send it to stderr. In a batch file this is achieved using >&2

Overriding Hooks

If a hook script rejects your commit then its decision is final. But you can build an override mechanism into the script itself using the Magic Word technique. If the script wants to reject the operation it first scans the log message for a special pass phrase, either a fixed phrase or perhaps the filename with a prefix. If it finds the magic word then it allows the commit to proceed. If the phrase is not found then it can block the commit with a message like “You didn't say the magic word” :-)

Checkout Links

If you want to make your Subversion repository available to others you may want to include a link to it from your website. One way to make this more accessible is to include a checkout link for other TortoiseSVN users.

When you install TortoiseSVN, it registers a new tsvn: protocol. When a TortoiseSVN user clicks on such a link, the checkout dialog will open automatically with the repository URL already filled in.

To include such a link in your own html page, you need to add code which looks something like this:

<a href="tsvn:http://project.domain.org/svn/trunk">
</a>

Of course it would look even better if you included a suitable picture. You can use the TortoiseSVN logo or you can provide your own image.

<a href="tsvn:http://project.domain.org/svn/trunk">
<img src=TortoiseCheckout.png></a>

You can also make the link point to a specific revision, for example

<a href="tsvn:http://project.domain.org/svn/trunk?100">
</a>

Accessing the Repository

To use TortoiseSVN (or any other Subversion client), you need a place where your repositories are located. You can either store your repositories locally and access them using the file:// protocol or you can place them on a server and access them with the http:// or svn:// protocols. The two server protocols can also be encrypted. You use https:// or svn+ssh://, or you can use svn:// with SASL.

If you are using a public hosting service such as Google Code or your server has already been setup by someone else then there is nothing else you need to do. Move along to Chapter 4, Daily Use Guide.

If you don't have a server and you work alone, or if you are just evaluating Subversion and TortoiseSVN in isolation, then local repositories are probably your best choice. Just create a repository on your own PC as described earlier in Chapter 3, The Repository. You can skip the rest of this chapter and go directly to Chapter 4, Daily Use Guide to find out how to start using it.

If you were thinking about setting up a multi-user repository on a network share, think again. Read the section called “Accessing a Repository on a Network Share” to find out why we think this is a bad idea. Setting up a server is not as hard as it sounds, and will give you better reliability and probably speed too.

The next sections are a step-by-step guide on how you can set up such a server on a Windows machine. Of course you can also set up a server on a Linux machine, but that is beyond the scope of this guide. More detailed information on the Subversion server options, and how to choose the best architecture for your situation, can be found in the Subversion book under Server Configuration .

Svnserve Based Server

Introduction

Subversion includes Svnserve - a lightweight stand-alone server which uses a custom protocol over an ordinary TCP/IP connection. It is ideal for smaller installations, or where a full blown Apache server cannot be used.

In most cases svnserve is easier to setup and runs faster than the Apache based server, although it doesn't have some of the advanced features. And now that SASL support is included it is easy to secure as well.

Installing svnserve

  1. Get the latest version of Subversion from http://subversion.apache.org/getting.html . Alternatively get a pre-packaged installer from CollabNet at http://www.collab.net/downloads/subversion . This installer will setup svnserve as a Windows service, and also includes some of the tools you need if you are going to use SASL for security.

  2. If you already have a version of Subversion installed, and svnserve is running, you will need to stop it before continuing.

  3. Run the Subversion installer. If you run the installer on your server (recommended) you can skip step 4.

  4. Open the windows-explorer, go to the installation directory of Subversion (usually C:\Program Files\Subversion) and in the bin directory, find the files svnserve.exe, intl3_svn.dll, libapr.dll, libapriconv.dll, libapriutil.dll, libdb*.dll, libeay32.dll and ssleay32.dll - copy these files, or just copy all of the bin directory, into a directory on your server e.g. c:\svnserve

Running svnserve

Now that svnserve is installed, you need it running on your server. The simplest approach is to run the following from a DOS shell or create a windows shortcut:

svnserve.exe --daemon

svnserve will now start waiting for incoming requests on port 3690. The --daemon switch tells svnserve to run as a daemon process, so it will always exist until it is manually terminated.

If you have not yet created a repository, follow the instructions given with the Apache server setup the section called “Configuration”.

To test that svnserve is working, use TortoiseSVNRepo-Browser to view a repository.

Assuming your repository is located in c:\repos\TestRepo, and your server is called localhost, enter:

svn://localhost/repos/TestRepo

when prompted by the repo browser.

You can also increase security and save time entering URLs with svnserve by using the --root switch to set the root location and restrict access to a specified directory on the server:

svnserve.exe --daemon --root drive:\path\to\repository\root

Using the previous test as a guide, svnserve would now run as:

svnserve.exe --daemon --root c:\repos

And in TortoiseSVN our repo-browser URL is now shortened to:

svn://localhost/TestRepo

Note that the --root switch is also needed if your repository is located on a different partition or drive than the location of svnserve on your server.

Svnserve will service any number of repositories. Just locate them somewhere below the root folder you just defined, and access them using a URL relative to that root.

Warning

Do not create or access a Berkeley DB repository on a network share. It cannot exist on a remote filesystem. Not even if you have the network drive mapped to a drive letter. If you attempt to use Berkeley DB on a network share, the results are unpredictable - you may see mysterious errors right away, or it may be months before you discover that your repository database is subtly corrupted.

Run svnserve as a Service

Running svnserve as a user is usually not the best way. It means always having a user logged in on your server, and remembering to restart it after a reboot. A better way is to run svnserve as a windows service. Starting with Subversion 1.4, svnserve can be installed as a native windows service.

To install svnserve as a native windows service, execute the following command all on one line to create a service which is automatically started when windows starts.

sc create svnserve binpath= "c:\svnserve\svnserve.exe --service 
    --root c:\repos" displayname= "Subversion" depend= tcpip 
    start= auto

If any of the paths include spaces, you have to use (escaped) quotes around the path, like this:

sc create svnserve binpath= "
    \"C:\Program Files\Subversion\bin\svnserve.exe\"
    --service --root c:\repos" displayname= "Subversion" 
    depend= tcpip start= auto

You can also add a description after creating the service. This will show up in the Windows Services Manager.

sc description svnserve "Subversion server (svnserve)"

Note the rather unusual command line format used by sc. In the key= value pairs there must be no space between the key and the = but there must be a space before the value.

Tip

Microsoft now recommend services to be run as under either the Local Service or Network Service account. Refer to The Services and Service Accounts Security Planning Guide . To create the service under the Local Service account, append the following to the example above.

obj= "NT AUTHORITY\LocalService"

Note that you would have to give the Local Service account appropriate rights to both Subversion and your repositories, as well as any applications which are used by hook scripts. The built-in group for this is called "LOCAL SERVICE".

Once you have installed the service, you need to go to the services manager to start it (this time only; it will start automatically when the server reboots).

For more detailed information, refer to Windows Service Support for Svnserve .

If you installed an earlier version of svnserve using the SVNService wrapper, and you now want to use the native support instead, you will need to unregister the wrapper as a service (remember to stop the service first!). Simply use the command

svnservice -remove

to remove the service registry entry.

Basic Authentication with svnserve

The default svnserve setup provides anonymous read-only access. This means that you can use an svn:// URL to checkout and update, or use the repo-browser in TortoiseSVN to view the repository, but you won't be able to commit any changes.

To enable write access to a repository, you need to edit the conf/svnserve.conf file in your repository directory. This file controls the configuration of the svnserve daemon, and also contains useful documentation.

You can enable anonymous write access by simply setting:

[general]
anon-access = write

However, you will not know who has made changes to a repository, as the svn:author property will be empty. You will also be unable to control who makes changes to a repository. This is a somewhat risky setup!

One way to overcome this is to create a password database:

[general]
anon-access = none
auth-access = write
password-db = userfile

Where userfile is a file which exists in the same directory as svnserve.conf. This file can live elsewhere in your file system (useful for when you have multiple repositories which require the same access rights) and may be referenced using an absolute path, or a path relative to the conf directory. If you include a path, it must be written /the/unix/way. Using \ or drive letters will not work. The userfile should have a structure of:

[users]
username = password
...

This example would deny all access for unauthenticated (anonymous) users, and give read-write access to users listed in userfile.

Tip

If you maintain multiple repositories using the same password database, the use of an authentication realm will make life easier for users, as TortoiseSVN can cache your credentials so that you only have to enter them once. More information can be found in the Subversion book, specifically in the sections Create a 'users' file and realm and Client Credentials Caching

Better Security with SASL

What is SASL?

The Cyrus Simple Authentication and Security Layer is open source software written by Carnegie Mellon University. It adds generic authentication and encryption capabilities to any network protocol, and as of Subversion 1.5 and later, both the svnserve server and TortoiseSVN client know how to make use of this library.

For a more complete discussion of the options available, you should look at the Subversion book in the section Using svnserve with SASL . If you are just looking for a simple way to set up secure authentication and encryption on a Windows server, so that your repository can be accessed safely over the big bad Internet, read on.

SASL Authentication

To activate specific SASL mechanisms on the server, you'll need to do three things. First, create a [sasl] section in your repository's svnserve.conf file, with this key-value pair:

use-sasl = true

Second, create a file called svn.conf in a convenient location - typically in the directory where subversion is installed.

Thirdly, create two new registry entries to tell SASL where to find things. Create a registry key named [HKEY_LOCAL_MACHINE\SOFTWARE\Carnegie Mellon\Project Cyrus\SASL Library] and place two new string values inside it: SearchPath set to the directory path containing the sasl*.dll plug-ins (normally in the Subversion install directory), and ConfFile set to the directory containing the svn.conf file. If you used the CollabNet installer, these registry keys will already have been created for you.

Edit the svn.conf file to contain the following:

pwcheck_method: auxprop
auxprop_plugin: sasldb
mech_list: DIGEST-MD5
sasldb_path: C:\TortoiseSVN\sasldb

The last line shows the location of the authentication database, which is a file called sasldb. This could go anywhere, but a convenient choice is the repository parent path. Make sure that the svnserve service has read access to this file.

If svnserve was already running, you will need to restart it to ensure it reads the updated configuration.

Now that everything is set up, all you need to do is create some users and passwords. To do this you need the saslpasswd2 program. If you used the CollabNet installer, that program will be in the install directory. Use a command something like this:

saslpasswd2 -c -f C:\TortoiseSVN\sasldb -u realm username

The -f switch gives the database location, realm must be the same as the value you defined in your repository's svnserve.conf file, and username is exactly what you expect it to be. Note that the realm is not allowed to contain space characters.

You can list the usernames stored in the database using the sasldblistusers2 program.

SASL Encryption

To enable or disable different levels of encryption, you can set two values in your repository's svnserve.conf file:

[sasl]
use-sasl = true
min-encryption = 128
max-encryption = 256

The min-encryption and max-encryption variables control the level of encryption demanded by the server. To disable encryption completely, set both values to 0. To enable simple checksumming of data (i.e., prevent tampering and guarantee data integrity without encryption), set both values to 1. If you wish to allow (but not require) encryption, set the minimum value to 0, and the maximum value to some bit-length. To require encryption unconditionally, set both values to numbers greater than 1. In our previous example, we require clients to do at least 128-bit encryption, but no more than 256-bit encryption.

Authentication with svn+ssh

Another way to authenticate users with a svnserve based server is to use a secure shell (SSH) to tunnel requests through. It is not as simple to set up as SASL, but it may be useful is some cases.

With this approach, svnserve is not run as a daemon process, rather, the secure shell starts svnserve for you, running it as the SSH authenticated user. To enable this, you need a secure shell daemon on your server.

A basic method for setting up your server is given in Appendix G, Securing Svnserve using SSH. You can find other SSH topics within the FAQ by searching for “SSH”.

Further information about svnserve can be found in the Version Control with Subversion .

Path-based Authorization with svnserve

Starting with Subversion 1.3, svnserve supports the same mod_authz_svn path-based authorization scheme that is available with the Apache server. You need to edit the conf/svnserve.conf file in your repository directory and add a line referring to your authorization file.

[general]
authz-db = authz

Here, authz is a file you create to define the access permissions. You can use a separate file for each repository, or you can use the same file for several repositories. Read the section called “Path-Based Authorization” for a description of the file format.

Apache Based Server

Introduction

The most flexible of all possible server setups for Subversion is the Apache based one. Although a bit more complicated to set up, it offers benefits that other servers cannot:

WebDAV

The Apache based Subversion server uses the WebDAV protocol which is supported by many other programs as well. You could e.g. mount such a repository as a “Web folder” in the Windows explorer and then access it like any other folder in the file system.

Browsing The Repository

You can point your browser to the URL of your repository and browse the contents of it without having a Subversion client installed. This gives access to your data to a much wider circle of users.

Authentication

You can use any authentication mechanism Apache supports, including SSPI and LDAP.

Security

Since Apache is very stable and secure, you automatically get the same security for your repository. This includes SSL encryption.

Installing Apache

The first thing you need before installing Apache is a computer with Windows 2000, Windows XP+SP1, Windows 2003, Vista or Server 2008.

Warning

Please note that Windows XP without the service pack 1 will lead to bogus network data and could therefore corrupt your repository!

  1. Download the latest version of the Apache web server from http://httpd.apache.org/download.cgi . Make sure that you download the version 2.2.x - the version 1.3.xx won't work!

    The msi installer for Apache can be found by clicking on other files, then browse to binaries/win32. You may want to choose the msi file apache-2.2.x-win32-x86-openssl-0.9.x.msi (the one that includes OpenSSL).

  2. Once you have the Apache2 installer you can double click on it and it will guide you through the installation process. Make sure that you enter the server-URL correctly (if you don't have a DNS name for your server just enter the IP-address). I recommend to install Apache for All Users, on Port 80, as a Service. Note: if you already have IIS or any other program running which listens on port 80 the installation might fail. If that happens, go to the programs directory, \Apache Group\Apache2\conf and locate the file httpd.conf. Edit that file so that Listen 80 is changed to a free port, e.g. Listen 81. Then restart the installation - this time it should finish without problems.

  3. Now test if the Apache web server is running correctly by pointing your web browser to http://localhost/ - a preconfigured Website should show up.

Caution

If you decide to install Apache as a service, be warned that by default it will run as the local system account. It would be a more secure practice for you to create a separate account for Apache to run as.

Make sure that the account on the server that Apache is running as has an explicit entry in the repository directory's access control list (right-click directory | properties | security), with full control. Otherwise, users will not be able to commit their changes.

Even if Apache runs as local system, you still need such an entry (which will be the SYSTEM account in this case).

If Apache does not have this permission set up, your users will get “Access denied” error messages, which show up in the Apache error log as error 500.

Installing Subversion

  1. Download the latest version of the Subversion Win32 binaries for Apache. Be sure to get the right version to integrate with your version of Apache, otherwise you will get an obscure error message when you try to restart. If you have Apache 2.2.x go to http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=8100 .

  2. Run the Subversion installer and follow the instructions. If the Subversion installer recognized that you've installed Apache, then you're almost done. If it couldn't find an Apache server then you have to do some additional steps.

  3. Using the windows explorer, go to the installation directory of Subversion (usually c:\program files\Subversion) and find the files /httpd/mod_dav_svn.so and mod_authz_svn.so. Copy these files to the Apache modules directory (usually c:\program files\apache group\apache2\modules ).

  4. Copy the file /bin/libdb*.dll and /bin/intl3_svn.dll from the Subversion installation directory to the Apache bin directory.

  5. Edit Apache's configuration file (usually C:\Program Files\Apache Group\Apache2\conf\httpd.conf) with a text editor such as Notepad and make the following changes:

    Uncomment (remove the '#' mark) the following lines:

    #LoadModule dav_fs_module modules/mod_dav_fs.so
    #LoadModule dav_module modules/mod_dav.so
    

    Add the following two lines to the end of the LoadModule section.

    LoadModule dav_svn_module modules/mod_dav_svn.so
    LoadModule authz_svn_module modules/mod_authz_svn.so
    

Configuration

Now you have set up Apache and Subversion, but Apache doesn't know how to handle Subversion clients like TortoiseSVN yet. To get Apache to know which URL will be used for Subversion repositories you have to edit the Apache configuration file (usually located in c:\program files\apache group\apache2\conf\httpd.conf) with any text editor you like (e.g. Notepad):

  1. At the end of the config file add the following lines:

    <Location /svn>
      DAV svn
      SVNListParentPath on
      SVNParentPath D:\SVN
      #SVNIndexXSLT "/svnindex.xsl"
      AuthType Basic
      AuthName "Subversion repositories"
      AuthUserFile passwd
      #AuthzSVNAccessFile svnaccessfile
      Require valid-user
    </Location>
    

    This configures Apache so that all your Subversion repositories are physically located below D:\SVN. The repositories are served to the outside world from the URL: http://MyServer/svn/ . Access is restricted to known users/passwords listed in the passwd file.

  2. To create the passwd file, open the command prompt (DOS-Box) again, change to the apache2 folder (usually c:\program files\apache group\apache2) and create the file by entering

    bin\htpasswd -c passwd <username>
    

    This will create a file with the name passwd which is used for authentication. Additional users can be added with

    bin\htpasswd passwd <username>
    

  3. Restart the Apache service again.

  4. Point your browser to http://MyServer/svn/MyNewRepository (where MyNewRepository is the name of the Subversion repository you created before). If all went well you should be prompted for a username and password, then you can see the contents of your repository.

A short explanation of what you just entered:

Table 3.1. Apache httpd.conf Settings

SettingExplanation
<Location /svn> means that the Subversion repositories are available from the URL http://MyServer/svn/
DAV svn tells Apache which module will be responsible to serve that URL - in this case the Subversion module.
SVNListParentPath on For Subversion version 1.3 and higher, this directive enables listing all the available repositories under SVNParentPath.
SVNParentPath D:\SVN tells Subversion to look for repositories below D:\SVN
SVNIndexXSLT "/svnindex.xsl" Used to make the browsing with a web browser prettier.
AuthType Basic is to activate basic authentication, i.e. Username/password
AuthName "Subversion repositories" is used as an information whenever an authentication dialog pops up to tell the user what the authentication is for
AuthUserFile passwd specifies which password file to use for authentication
AuthzSVNAccessFile Location of the Access file for paths inside a Subversion repository
Require valid-user specifies that only users who entered a correct username/password are allowed to access the URL


But that's just an example. There are many, many more possibilities of what you can do with the Apache web server.

  • If you want your repository to have read access for everyone but write access only for specific users you can change the line

    Require valid-user
    

    to

    <LimitExcept GET PROPFIND OPTIONS REPORT>
    Require valid-user
    </LimitExcept>
    

  • Using a passwd file limits and grants access to all of your repositories as a unit. If you want more control over which users have access to each folder inside a repository you can uncomment the line

    #AuthzSVNAccessFile svnaccessfile
    

    and create a Subversion access file. Apache will make sure that only valid users are able to access your /svn location, and will then pass the username to Subversion's AuthzSVNAccessFile module so that it can enforce more granular access based upon rules listed in the Subversion access file. Note that paths are specified either as repos:path or simply path. If you don't specify a particular repository, that access rule will apply to all repositories under SVNParentPath. The format of the authorization-policy file used by mod_authz_svn is described in the section called “Path-Based Authorization”

  • To make browsing the repository with a web browser 'prettier', uncomment the line

    #SVNIndexXSLT "/svnindex.xsl"
    

    and put the files svnindex.xsl, svnindex.css and menucheckout.ico in your document root directory (usually C:/Program Files/Apache Group/Apache2/htdocs). The directory is set with the DocumentRoot directive in your Apache config file.

    You can get those three files directly from our source repository at http://tortoisesvn.tigris.org/svn/tortoisesvn/trunk/contrib/svnindex . (the section called “TortoiseSVN is free!” explains how to access the TortoiseSVN source repository).

    The XSL file from the TortoiseSVN repository has a nice gimmick: if you browse the repository with your web browser, then every folder in your repository has an icon on the right shown. If you click on that icon, the TortoiseSVN checkout dialog is started for this URL.

Multiple Repositories

If you used the SVNParentPath directive then you don't have to change the Apache config file every time you add a new Subversion repository. Simply create the new repository under the same location as the first repository and you're done! In my company I have direct access to that specific folder on the server via SMB (normal windows file access). So I just create a new folder there, run the TortoiseSVN command TortoiseSVNCreate repository here... and a new project has a home...

If you are using Subversion 1.3 or later, you can use the SVNListParentPath on directive to allow Apache to produce a listing of all available projects if you point your browser at the parent path rather than at a specific repository.

Path-Based Authorization

The mod_authz_svn module permits fine-grained control of access permissions based on user names and repository paths. This is available with the Apache server, and as of Subversion 1.3 it is available with svnserve as well.

An example file would look like this:

[groups]
admin = john, kate
devteam1 = john, rachel, sally
devteam2 = kate, peter, mark
docs = bob, jane, mike
training = zak
# Default access rule for ALL repositories
# Everyone can read, admins can write, Dan German is excluded.
[/]
* = r
@admin = rw
dangerman =
# Allow developers complete access to their project repos
[proj1:/]
@devteam1 = rw
[proj2:/]
@devteam2 = rw
[bigproj:/]
@devteam1 = rw
@devteam2 = rw
trevor = rw
# Give the doc people write access to all the docs folders
[/trunk/doc]
@docs = rw
# Give trainees write access in the training repository only
[TrainingRepos:/]
@training = rw

Note that checking every path can be an expensive operation, particularly in the case of the revision log. The server checks every changed path in each revision and checks it for readability, which can be time-consuming on revisions which affect large numbers of files.

Authentication and authorization are separate processes. If a user wants to gain access to a repository path, she has to meet both, the usual authentication requirements and the authorization requirements of the access file.

Authentication With a Windows Domain

As you might have noticed you need to make a username/password entry in the passwd file for each user separately. And if (for security reasons) you want your users to periodically change their passwords you have to make the change manually.

But there's a solution for that problem - at least if you're accessing the repository from inside a LAN with a windows domain controller: mod_auth_sspi!

The original SSPI module was offered by Syneapps including source code. But the development for it has been stopped. But don't despair, the community has picked it up and improved it. It has a new home on SourceForge .

  • Download the module which matches your apache version, then copy the file mod_auth_sspi.so into the Apache modules folder.

  • Edit the Apache config file: add the line

    LoadModule sspi_auth_module modules/mod_auth_sspi.so
    

    to the LoadModule section. Make sure you insert this line before the line

    LoadModule auth_module modules/mod_auth.so
    

  • To make the Subversion location use this type of authentication you have to change the line

    AuthType Basic
    

    to

    AuthType SSPI
    

    also you need to add

    SSPIAuth On
    SSPIAuthoritative On
    SSPIDomain <domaincontroller>
    SSPIOmitDomain on
    SSPIUsernameCase lower
    SSPIPerRequestAuth on
    SSPIOfferBasic On
    

    within the <Location /svn> block. If you don't have a domain controller, leave the name of the domain control as <domaincontroller>.

Note that if you are authenticating using SSPI, then you don't need the AuthUserFile line to define a password file any more. Apache authenticates your username and password against your windows domain instead. You will need to update the users list in your svnaccessfile to reference DOMAIN\username as well.

Important

The SSPI authentication is only enabled for SSL secured connections (https). If you're only using normal http connections to your server, it won't work.

To enable SSL on your server, see the chapter: the section called “Securing the server with SSL”

Tip

Subversion AuthzSVNAccessFile files are case sensitive in regard to user names (JUser is different from juser).

In Microsoft's world, Windows domains and user names are not case sensitive. Even so, some network administrators like to create user accounts in CamelCase (e.g. JUser).

This difference can bite you when using SSPI authentication as the windows domain and user names are passed to Subversion in the same case as the user types them in at the prompt. Internet Explorer often passes the username to Apache automatically using whatever case the account was created with.

The end result is that you may need at least two entries in your AuthzSVNAccessFile for each user -- a lowercase entry and an entry in the same case that Internet Explorer passes to Apache. You will also need to train your users to also type in their credentials using lower case when accessing repositories via TortoiseSVN.

Apache's Error and Access logs are your best friend in deciphering problems such as these as they will help you determine the username string passed onto Subversion's AuthzSVNAccessFile module. You may need to experiment with the exact format of the user string in the svnaccessfile (e.g. DOMAIN\user vs. DOMAIN//user) in order to get everything working.

Multiple Authentication Sources

It is also possible to have more than one authentication source for your Subversion repository. To do this, you need to make each authentication type non-authoritative, so that Apache will check multiple sources for a matching username/password.

A common scenario is to use both Windows domain authentication and a passwd file, so that you can provide SVN access to users who don't have a Windows domain login.

  • To enable both Windows domain and passwd file authentication, add the following entries within the <Location> block of your Apache config file:

    AuthBasicAuthoritative Off
    SSPIAuthoritative Off
    

Here is an example of the full Apache configuration for combined Windows domain and passwd file authentication:

<Location /svn>
  DAV svn
  SVNListParentPath on
  SVNParentPath D:\SVN

  AuthName "Subversion repositories"
  AuthzSVNAccessFile svnaccessfile.txt

# NT Domain Logins.
  AuthType SSPI
  SSPIAuth On
  SSPIAuthoritative Off
  SSPIDomain <domaincontroller>
  SSPIOfferBasic On

# Htpasswd Logins.
  AuthType Basic
  AuthBasicAuthoritative Off
  AuthUserFile passwd

  Require valid-user
</Location>

Securing the server with SSL

Even though Apache 2.2.x has OpenSSL support, it is not activated by default. You need to activate this manually.

  1. In the apache config file, uncomment the lines:

    #LoadModule ssl_module modules/mod_ssl.so
    

    and at the bottom

    #Include conf/extra/httpd-ssl.conf
    

    then change the line (on one line)

    SSLMutex "file:C:/Program Files/Apache Software Foundation/\
    Apache2.2/logs/ssl_mutex"
    

    to

    SSLMutex default
    

  2. Next you need to create an SSL certificate. To do that open a command prompt (DOS-Box) and change to the Apache folder (e.g. C:\program files\apache group\apache2) and type the following command:

    bin\openssl req -config conf\openssl.cnf -new -out my-server.csr
    

    You will be asked for a passphrase. Please don't use simple words but whole sentences, e.g. a part of a poem. The longer the phrase the better. Also you have to enter the URL of your server. All other questions are optional but we recommend you fill those in too.

    Normally the privkey.pem file is created automatically, but if it isn't you need to type this command to generate it:

    bin\openssl genrsa -out conf\privkey.pem 2048
    

    Next type the commands

    bin\openssl rsa -in conf\privkey.pem -out conf\server.key
    

    and (on one line)

    bin\openssl req -new -key conf\server.key -out conf\server.csr \
    -config conf\openssl.cnf
    

    and then (on one line)

    bin\openssl x509 -in conf\server.csr -out conf\server.cert
                     -req -signkey conf\server.key -days 4000
    

    This will create a certificate which will expire in 4000 days. And finally enter (on one line):

    bin\openssl x509 -in conf\server.cert -out conf\server.der.crt
                     -outform DER
    

    These commands created some files in the Apache conf folder (server.der.crt, server.csr, server.key, .rnd, privkey.pem, server.cert).

  3. Restart the Apache service.

  4. Point your browser to https://servername/svn/project ...

SSL and Internet Explorer

If you're securing your server with SSL and use authentication against a windows domain you will encounter that browsing the repository with the Internet Explorer doesn't work anymore. Don't worry - this is only the Internet Explorer not able to authenticate. Other browsers don't have that problem and TortoiseSVN and any other Subversion client are still able to authenticate.

If you still want to use IE to browse the repository you can either:

  • define a separate <Location /path> directive in the Apache config file, and add the SSPIBasicPreferred On. This will allow IE to authenticate again, but other browsers and Subversion won't be able to authenticate against that location.

  • Offer browsing with unencrypted authentication (without SSL) too. Strangely IE doesn't have any problems with authenticating if the connection is not secured with SSL.

  • In the SSL "standard" setup there's often the following statement in Apache's virtual SSL host:

    SetEnvIf User-Agent ".*MSIE.*" \
                 nokeepalive ssl-unclean-shutdown \
                 downgrade-1.0 force-response-1.0
    

    There are (were?) good reasons for this configuration, see http://www.modssl.org/docs/2.8/ssl_faq.html#ToC49 But if you want NTLM authentication you have to use keepalive. If You uncomment the whole SetEnvIf you should be able to authenticate IE with windows authentication over SSL against the Apache on Win32 with included mod_auth_sspi.

Forcing SSL access

When you've set up SSL to make your repository more secure, you might want to disable the normal access via non-SSL (http) and only allow https access. To do this, you have to add another directive to the Subversion <Location> block: SSLRequireSSL.

An example <Location> block would look like this:

<Location /svn>
  DAV svn
  SVNParentPath D:\SVN
  SSLRequireSSL
  AuthType Basic
  AuthName "Subversion repositories"
  AuthUserFile passwd
  #AuthzSVNAccessFile svnaccessfile
  Require valid-user
</Location>

Using client certificates with virtual SSL hosts

Sent to the TortoiseSVN mailing list by Nigel Green. Thanks!

In some server configurations you may need to setup a single server containing 2 virtual SSL hosts: The first one for public web access, with no requirement for a client certificate. The second one to be secure with a required client certificate, running a Subversion server.

Adding an SSLVerifyClient Optional directive to the per-server section of the Apache configuration (i.e. outside of any VirtualHost and Directory blocks) forces Apache to request a client Certificate in the initial SSL handshake. Due to a bug in mod_ssl it is essential that the certificate is requested at this point as it does not work if the SSL connection is re-negotiated.

The solution is to add the following directive to the virtual host directory that you want to lock down for Subversion:

SSLRequire %{SSL_CLIENT_VERIFY} eq "SUCCESS"

This directive grants access to the directory only if a client certificate was received and verified successfully.

To summarise, the relevant lines of the Apache configuration are:

SSLVerifyClient Optional

### Virtual host configuration for the PUBLIC host 
### (not requiring a certificate)

<VirtualHost 127.0.0.1:443>
  <Directory "pathtopublicfileroot">
  </Directory>
</VirtualHost>

### Virtual host configuration for SUBVERSION 
### (requiring a client certificate)
<VirtualHost 127.0.0.1:443>
  <Directory "subversion host root path">
    SSLRequire %{SSL_CLIENT_VERIFY} eq "SUCCESS"
  </Directory>

  <Location /svn>
    DAV svn
    SVNParentPath /pathtorepository
  </Location>
</VirtualHost>

Chapter 4. Daily Use Guide

Table of Contents

Getting Started
Icon Overlays
Context Menus
Drag and Drop
Common Shortcuts
Authentication
Maximizing Windows
Importing Data Into A Repository
Import
Import in Place
Special Files
Checking Out A Working Copy
Checkout Depth
Committing Your Changes To The Repository
The Commit Dialog
Change Lists
Excluding Items from the Commit List
Commit Log Messages
Commit Progress
Update Your Working Copy With Changes From Others
Resolving Conflicts
File Conflicts
Tree Conflicts
Getting Status Information
Icon Overlays
TortoiseSVN Columns In Windows Explorer
Local and Remote Status
Viewing Diffs
Change Lists
Revision Log Dialog
Invoking the Revision Log Dialog
Revision Log Actions
Getting Additional Information
Getting more log messages
Current Working Copy Revision
Merge Tracking Features
Changing the Log Message and Author
Filtering Log Messages
Statistical Information
Offline Mode
Refreshing the View
Viewing Differences
File Differences
Line-end and Whitespace Options
Comparing Folders
Diffing Images Using TortoiseIDiff
External Diff/Merge Tools
Adding New Files And Directories
Copying/Moving/Renaming Files and Folders
Ignoring Files And Directories
Pattern Matching in Ignore Lists
Deleting, Moving and Renaming
Deleting files and folders
Moving files and folders
Changing case in a filename
Dealing with filename case conflicts
Repairing File Renames
Deleting Unversioned Files
Undo Changes
Cleanup
Project Settings
Subversion Properties
TortoiseSVN Project Properties
External Items
External Folders
External Files
Branching / Tagging
Creating a Branch or Tag
Other ways to create a branch or tag
To Checkout or to Switch...
Merging
Merging a Range of Revisions
Reintegrate a branch
Merging Two Different Trees
Merge Options
Reviewing the Merge Results
Merge Tracking
Handling Conflicts during Merge
Merge a Completed Branch
Feature Branch Maintenance
Locking
How Locking Works in Subversion
Getting a Lock
Releasing a Lock
Checking Lock Status
Making Non-locked Files Read-Only
The Locking Hook Scripts
Creating and Applying Patches
Creating a Patch File
Applying a Patch File
Who Changed Which Line?
Blame for Files
Blame Differences
The Repository Browser
Revision Graphs
Revision Graph Nodes
Changing the View
Using the Graph
Refreshing the View
Pruning Trees
Exporting a Subversion Working Copy
Removing a working copy from version control
Relocating a working copy
Integration with Bug Tracking Systems / Issue Trackers
Adding Issue Numbers to Log Messages
Getting Information from the Issue Tracker
Integration with Web-based Repository Viewers
TortoiseSVN's Settings
General Settings
Revision Graph Settings
Icon Overlay Settings
Network Settings
External Program Settings
Saved Data Settings
Log Caching
Client Side Hook Scripts
TortoiseBlame Settings
Subversion Working Folders
Advanced Settings
Final Step

This document describes day to day usage of the TortoiseSVN client. It is not an introduction to version control systems, and not an introduction to Subversion (SVN). It is more like a place you may turn to when you know approximately what you want to do, but don't quite remember how to do it.

If you need an introduction to version control with Subversion, then we recommend you read the fantastic book: Version Control with Subversion .

This document is also a work in progress, just as TortoiseSVN and Subversion are. If you find any mistakes, please report them to the mailing list so we can update the documentation. Some of the screenshots in the Daily Use Guide (DUG) might not reflect the current state of the software. Please forgive us. We're working on TortoiseSVN in our free time.

In order to get the most out of the Daily Use Guide:

  • You should have installed TortoiseSVN already.

  • You should be familiar with version control systems.

  • You should know the basics of Subversion.

  • You should have set up a server and/or have access to a Subversion repository.

Getting Started

Icon Overlays

Figure 4.1. Explorer showing icon overlays

Explorer showing icon overlays


One of the most visible features of TortoiseSVN is the icon overlays which appear on files in your working copy. These show you at a glance which of your files have been modified. Refer to the section called “Icon Overlays” to find out what the different overlays represent.

Context Menus

Figure 4.2. Context menu for a directory under version control

Context menu for a directory under version control


All TortoiseSVN commands are invoked from the context menu of the windows explorer. Most are directly visible, when you right click on a file or folder. The commands that are available depend on whether the file or folder or its parent folder is under version control or not. You can also see the TortoiseSVN menu as part of the Explorer file menu.

Tip

Some commands which are very rarely used are only available in the extended context menu. To bring up the extended context menu, hold down the Shift key when you right-click.

In some cases you may see several TortoiseSVN entries. This is not a bug!

Figure 4.3. Explorer file menu for a shortcut in a versioned folder

Explorer file menu for a shortcut in a versioned folder


This example is for an unversioned shortcut within a versioned folder, and in the Explorer file menu there are three entries for TortoiseSVN. One is for the folder, one for the shortcut itself, and the third for the object the shortcut is pointing to. To help you distinguish between them, the icons have an indicator in the lower right corner to show whether the menu entry is for a file, a folder, a shortcut or for multiple selected items.

If you are using Windows 2000 you will find that the context menus are shown as plain text, without the menu icons shown above. We are aware that this was working in previous versions, but Microsoft has changed the way its icon handlers work for Vista, requiring us to use a different display method which unfortunately does not work on Windows 2000.

Drag and Drop

Figure 4.4. Right drag menu for a directory under version control

Right drag menu for a directory under version control


Other commands are available as drag handlers, when you right drag files or folders to a new location inside working copies or when you right drag a non-versioned file or folder into a directory which is under version control.

Common Shortcuts

Some common operations have well-known Windows shortcuts, but do not appear on buttons or in menus. If you can't work out how to do something obvious, like refreshing a view, check here.

F1

Help, of course.

F5

Refresh the current view. This is perhaps the single most useful one-key command. For example ... In Explorer this will refresh the icon overlays on your working copy. In the commit dialog it will re-scan the working copy to see what may need to be committed. In the Revision Log dialog it will contact the repository again to check for more recent changes.

Ctrl-A

Select all. This can be used if you get an error message and want to copy and paste into an email. Use Ctrl-A to select the error message and then ...

Ctrl-C

... Copy the selected text.

Authentication

If the repository that you are trying to access is password protected, an authentication Dialog will show up.

Figure 4.5. Authentication Dialog

Authentication Dialog


Enter your username and password. The checkbox will make TortoiseSVN store the credentials in Subversion's default directory: %APPDATA%\Subversion\auth in three subdirectories:

  • svn.simple contains credentials for basic authentication (username/password). Note that passwords are stored using the WinCrypt API, not in plain text form.

  • svn.ssl.server contains SSL server certificates.

  • svn.username contains credentials for username-only authentication (no password needed).

If you want to clear the authentication cache for all servers, you can do so from the Saved Data page of TortoiseSVN's settings dialog. That button will clear all cached authentication data from the Subversion auth directories, as well as any authentication data stored in the registry by earlier versions of TortoiseSVN. Refer to the section called “Saved Data Settings”.

If you want to clear authentication for one realm only then you will have to dig into those directories, find the file which contains the information you want to clear and delete the file.

Some people like to have the authentication data deleted when they log off Windows, or on shutdown. The way to do that is to use a shutdown script to delete the %APPDATA%\Subversion\auth directory, e.g.

@echo off
rmdir /s /q "%APPDATA%\Subversion\auth"

You can find a description of how to install such scripts at windows-help-central.com .

For more information on how to set up your server for authentication and access control, refer to the section called “Accessing the Repository”

Maximizing Windows

Many of TortoiseSVN's dialogs have a lot of information to display, but it is often useful to maximize only the height, or only the width, rather than maximizing to fill the screen. As a convenience, there are shortcuts for this on the Maximize button. Use the middle mouse button to maximize vertically, and right mouse to maximize horizontally.

Importing Data Into A Repository

Import

If you are importing into an existing repository which already contains some projects, then the repository structure will already have been decided. If you are importing data into a new repository, then it is worth taking the time to think about how it will be organised. Read the section called “Repository Layout” for further advice.

This section describes the Subversion import command, which was designed for importing a directory hierarchy into the repository in one shot. Although it does the job, it has several shortcomings:

  • There is no way to select files and folders to include, aside from using the global ignore settings.

  • The folder imported does not become a working copy. You have to do a checkout to copy the files back from the server.

  • It is easy to import to the wrong folder level in the repository.

For these reasons we recommend that you do not use the import command at all but rather follow the two-step method described in the section called “Import in Place”. But since you are here, this is how the basic import works ...

Before you import your project into a repository you should:

  1. Remove all files which are not needed to build the project (temporary files, files which are generated by a compiler e.g. *.obj, compiled binaries, ...)

  2. Organize the files in folders and sub-folders. Although it is possible to rename/move files later it is highly recommended to get your project's structure straight before importing!

Now select the top-level folder of your project directory structure in the windows explorer and right click to open the context menu. Select the command TortoiseSVNImport... which brings up a dialog box:

Figure 4.6. The Import dialog

The Import dialog


In this dialog you have to enter the URL of the repository location where you want to import your project. It is very important to realise that the local folder you are importing does not itself appear in the repository, only its content. For example if you have a structure:

C:\Projects\Widget\source
C:\Projects\Widget\doc
C:\Projects\Widget\images

and you import C:\Projects\Widget into http://mydomain.com/svn/trunk then you may be surprised to find that your subdirectories go straight into trunk rather than being in a Widget subdirectory. You need to specify the subdirectory as part of the URL, http://mydomain.com/svn/trunk/Widget-X. Note that the import command will automatically create subdirectories within the repository if they do not exist.

The import message is used as a log message.

By default, files and folders which match the global-ignore patterns are not imported. To override this behaviour you can use the Include ignored files checkbox. Refer to the section called “General Settings” for more information on setting a global ignore pattern.

As soon as you press OK TortoiseSVN imports the complete directory tree including all files into the repository. The project is now stored in the repository under version control. Please note that the folder you imported is NOT under version control! To get a version-controlled working copy you need to do a Checkout of the version you just imported. Or read on to find out how to import a folder in place.

Import in Place

Assuming you already have a repository, and you want to add a new folder structure to it, just follow these steps:

  1. Use the repository browser to create a new project folder directly in the repository.

  2. Checkout the new folder over the top of the folder you want to import. You will get a warning that the local folder is not empty. Now you have a versioned top level folder with unversioned content.

  3. Use TortoiseSVNAdd... on this versioned folder to add some or all of the content. You can add and remove files, set svn:ignore properties on folders and make any other changes you need to.

  4. Commit the top level folder, and you have a new versioned tree, and a local working copy, created from your existing folder.

Special Files

Sometimes you need to have a file under version control which contains user specific data. That means you have a file which every developer/user needs to modify to suit his/her local setup. But versioning such a file is difficult because every user would commit his/her changes every time to the repository.

In such cases we suggest to use template files. You create a file which contains all the data your developers will need, add that file to version control and let the developers check this file out. Then, each developer has to make a copy of that file and rename that copy. After that, modifying the copy is not a problem anymore.

As an example, you can have a look at TortoiseSVN's build script. It calls a file named TortoiseVars.bat which doesn't exist in the repository. Only the file TortoiseVars.tmpl. TortoiseVars.tmpl is the template file which every developer has to create a copy from and rename that file to TortoiseVars.bat. Inside that file, we added comments so that the users will see which lines they have to edit and change according to their local setup to get it working.

So as not to disturb the users, we also added the file TortoiseVars.bat to the ignore list of its parent folder, i.e. we've set the Subversion property svn:ignore to include that filename. That way it won't show up as unversioned on every commit.

Checking Out A Working Copy

To obtain a working copy you need to do a checkout from a repository.

Select a directory in windows explorer where you want to place your working copy. Right click to pop up the context menu and select the command TortoiseSVNCheckout..., which brings up the following dialog box:

Figure 4.7. The Checkout dialog

The Checkout dialog


If you enter a folder name that does not yet exist, then a directory with that name is created.

Checkout Depth

You can choose the depth you want to checkout, which allows you to specify the depth of recursion into child folders. If you want just a few sections of a large tree, You can checkout the top level folder only, then update selected folders recursively.

Fully recursive

Checkout the entire tree, including all child folders and sub-folders.

Immediate children, including folders

Checkout the specified directory, including all files and child folders, but do not populate the child folders.

Only file children

Checkout the specified directory, including all files but do not checkout any child folders.

Only this item

Checkout the directory only. Do not populate it with files or child folders.

Working copy

Retain the depth specified in the working copy. This option is not used in the checkout dialog, but it is the default in all other dialogs which have a depth setting.

Exclude

Used to reduce working copy depth after a folder has already been populated. This option is only available in the Update to revision dialog.

If you check out a sparse working copy (i.e., by choosing something other than fully recursive for the checkout depth), you can fetch additional sub-folders by using the repository browser (the section called “The Repository Browser”) or the check for modifications dialog (the section called “Local and Remote Status”).

In the repository browser, Right click on the checked out folder, then use TortoiseSVNRepo-Browser to bring up the repository browser. Find the sub-folder you would like to add to your working copy, then use Context menuUpdate item to revision... That menu will only be visible if the selected item does not exist yet in your working copy, but the parent item does exist.

In the check for modifications dialog, first click on the button Check repository. The dialog will show all the files and folders which are in the repository but which you have not checked out as remotely added. Right click on the folder(s) you would like to add to your working copy, then use Context menuUpdate.

This feature is very useful when you only want to checkout parts of a large tree, but you want the convenience of updating a single working copy. Suppose you have a large tree which has sub-folders Project01 to Project99, and you only want to checkout Project03, Project25 and Project76/SubProj. Use these steps:

  1. Checkout the parent folder with depth “Only this item” You now have an empty top level folder.

  2. Select the new folder and use TortoiseSVNRepo browser to display the repository content.

  3. Right click on Project03 and Context menuUpdate item to revision.... Keep the default settings and click on OK. You now have that folder fully populated.

    Repeat the same process for Project25.

  4. Navigate to Project76/SubProj and do the same. This time note that the Project76 folder has no content except for SubProj, which itself is fully populated. Subversion has created the intermediate folders for you without populating them.

Changing working copy depth

Once you have checked out a working copy to a particular depth you can change that depth later to get more or less content using Context menuUpdate item to revision....

Using an older server

Pre-1.5 servers do not understand the working copy depth request, so they cannot always deal with requests efficiently. The command will still work, but an older server may send all the data, leaving the client to filter out what is not required, which may mean a lot of network traffic. If possible you should upgrade your server to 1.5.

If the project contains references to external projects which you do not want checked out at the same time, use the Omit externals checkbox.

Important

If Omit externals is checked, or if you wish to increase the depth value, you will have to perform updates to your working copy using TortoiseSVNUpdate to Revision... instead of TortoiseSVNUpdate. The standard update will include all externals and keep the existing depth.

It is recommended that you check out only the trunk part of the directory tree, or lower. If you specify the parent path of the directory tree in the URL then you might end up with a full hard disk since you will get a copy of the entire repository tree including every branch and tag of your project!

Exporting

Sometimes you may want to create a local copy without any of those .svn directories, e.g. to create a zipped tarball of your source. Read the section called “Exporting a Subversion Working Copy” to find out how to do that.

Committing Your Changes To The Repository

Sending the changes you made to your working copy is known as committing the changes. But before you commit you have to make sure that your working copy is up to date. You can either use TortoiseSVNUpdate directly. Or you can use TortoiseSVNCheck for Modifications first, to see which files have changed locally or on the server.

The Commit Dialog

If your working copy is up to date and there are no conflicts, you are ready to commit your changes. Select any file and/or folders you want to commit, then TortoiseSVNCommit....

Figure 4.8. The Commit dialog

The Commit dialog


The commit dialog will show you every changed file, including added, deleted and unversioned files. If you don't want a changed file to be committed, just uncheck that file. If you want to include an unversioned file, just check that file to add it to the commit.

Items which have been switched to a different repository path are also indicated using an (s) marker. You may have switched something while working on a branch and forgotten to switch back to trunk. This is your warning sign!

Commit files or folders?

When you commit files, the commit dialog shows only the files you have selected. When you commit a folder the commit dialog will select the changed files automatically. If you forget about a new file you created, committing the folder will find it anyway. Committing a folder does not mean that every file gets marked as changed; It just makes your life easier by doing more work for you.

If you have modified files which have been included from a different repository using svn:externals, those changes cannot be included in the same atomic commit. A warning symbol below the file list tells you if this has happened, and the tooltip explains that those external files have to be committed separately.

Many unversioned files in the commit dialog

If you think that the commit dialog shows you too many unversioned (e.g. compiler generated or editor backup) files, there are several ways to handle this. You can:

  • add the file (or a wildcard extension) to the list of files to exclude on the settings page. This will affect every working copy you have.

  • add the file to the svn:ignore list using TortoiseSVNAdd to ignore list This will only affect the directory on which you set the svn:ignore property. Using the SVN Property Dialog, you can alter the svn:ignore property for a directory.

Read the section called “Ignoring Files And Directories” for more information.

Double clicking on any modified file in the commit dialog will launch the external diff tool to show your changes. The context menu will give you more options, as shown in the screenshot. You can also drag files from here into another application such as a text editor or an IDE.

You can select or deselect items by clicking on the checkbox to the left of the item. For directories you can use Shift-select to make the action recursive.

The columns displayed in the bottom pane are customizable. If you right click on any column header you will see a context menu allowing you to select which columns are displayed. You can also change column width by using the drag handle which appears when you move the mouse over a column boundary. These customizations are preserved, so you will see the same headings next time.

By default when you commit changes, any locks that you hold on files are released automatically after the commit succeeds. If you want to keep those locks, make sure the Keep locks checkbox is checked. The default state of this checkbox is taken from the no_unlock option in the Subversion configuration file. Read the section called “General Settings” for information on how to edit the Subversion configuration file.

Drag and Drop

You can drag files into the commit dialog from elsewhere, so long as the working copies are checked out from the same repository. For example, you may have a huge working copy with several explorer windows open to look at distant folders of the hierarchy. If you want to avoid committing from the top level folder (with a lengthy folder crawl to check for changes) you can open the commit dialog for one folder and drag in items from the other windows to include within the same atomic commit.

You can drag unversioned files which reside within a working copy into the commit dialog, and they will be SVN added automatically.

Repairing External Renames

Sometimes files get renamed outside of Subversion, and they show up in the file list as a missing file and an unversioned file. To avoid losing the history you need to notify Subversion about the connection. Simply select both the old name (missing) and the new name (unversioned) and use Context MenuRepair Move to pair the two files as a rename.

Repairing External Copies

If you made a copy of a file but forgot to use the Subversion command to do so, you can repair that copy so the new file doesn't lose its history. Simply select both the old name (normal or modified) and the new name (unversioned) and use Context MenuRepair Copy to pair the two files as a copy.

Change Lists

The commit dialog supports Subversion's changelist feature to help with grouping related files together. Find out about this feature in the section called “Change Lists”.

Excluding Items from the Commit List

Sometimes you have versioned files that change frequently but that you really don't want to commit. Sometimes this indicates a flaw in your build process - why are those files versioned? should you be using template files? But occasionally it is inevitable. A classic reason is that your IDE changes a timestamp in the project file every time you build. The project file has to be versioned as it includes all the build settings, but it doesn't need to be committed just because the timestamp changed.

To help out in awkward cases like this, we have reserved a changelist called ignore-on-commit. Any file added to this changelist will automatically be unchecked in the commit dialog. You can still commit changes, but you have to select it manually in the commit dialog.

Commit Log Messages

Be sure to enter a log message which describes the changes you are committing. This will help you to see what happened and when, as you browse through the project log messages at a later date. The message can be as long or as brief as you like; many projects have guidelines for what should be included, the language to use, and sometimes even a strict format.

You can apply simple formatting to your log messages using a convention similar to that used within emails. To apply styling to text, use *text* for bold, _text_ for underlining, and ^text^ for italics.

Figure 4.9. The Commit Dialog Spellchecker

The Commit Dialog Spellchecker


TortoiseSVN includes a spellchecker to help you get your log messages right. This will highlight any mis-spelled words. Use the context menu to access the suggested corrections. Of course, it doesn't know every technical term that you do, so correctly spelt words will sometimes show up as errors. But don't worry. You can just add them to your personal dictionary using the context menu.

The log message window also includes a filename and function auto-completion facility. This uses regular expressions to extract class and function names from the (text) files you are committing, as well as the filenames themselves. If a word you are typing matches anything in the list (after you have typed at least 3 characters, or pressed Ctrl+Space), a drop-down appears allowing you to select the full name. The regular expressions supplied with TortoiseSVN are held in the TortoiseSVN installation bin folder. You can also define your own regexes and store them in %APPDATA%\TortoiseSVN\autolist.txt. Of course your private autolist will not be overwritten when you update your installation of TortoiseSVN. If you are unfamiliar with regular expressions, take a look at the introduction at http://en.wikipedia.org/wiki/Regular_expression , and the online documentation and tutorial at http://www.regular-expressions.info/ .

Getting the regex just right can be tricky, so to help you sort out a suitable expression there is a test dialog which allows you to enter an expression and then type in filenames to test it against. Start it from the command prompt using the command TortoiseProc.exe /command:autotexttest

You can re-use previously entered log messages. Just click on Recent messages to view a list of the last few messages you entered for this working copy. The number of stored messages can be customized in the TortoiseSVN settings dialog.

You can clear all stored commit messages from the Saved data page of TortoiseSVN's settings, or you can clear individual messages from within the Recent messages dialog using the Delete key.

If you want to include the checked paths in your log message, you can use the command Context MenuPaste filename list in the edit control.

Another way to insert the paths into the log message is to simply drag the files from the file list onto the edit control.

Special Folder Properties

There are several special folder properties which can be used to help give more control over the formatting of commit log messages and the language used by the spellchecker module. Read the section called “Project Settings” for further information.

Integration with Bug Tracking Tools

If you have activated the bug tracking system, you can set one or more Issues in the Bug-ID / Issue-Nr: text box. Multiple issues should be comma separated. Alternatively, if you are using regex-based bug tracking support, just add your issue references as part of the log message. Learn more in the section called “Integration with Bug Tracking Systems / Issue Trackers”.

Commit Progress

After pressing OK, a dialog appears displaying the progress of the commit.

Figure 4.10. The Progress dialog showing a commit in progress

The Progress dialog showing a commit in progress


The progress dialog uses colour coding to highlight different commit actions

Blue

Committing a modification.

Purple

Committing a new addition.

Dark red

Committing a deletion or a replacement.

Black

All other items.

This is the default colour scheme, but you can customise those colours using the settings dialog. Read the section called “TortoiseSVN Colour Settings” for more information.

Update Your Working Copy With Changes From Others

Figure 4.11. Progress dialog showing finished update

Progress dialog showing finished update


Periodically, you should ensure that changes done by others get incorporated in your local working copy. The process of getting changes from the server to your local copy is known as updating. Updating may be done on single files, a set of selected files, or recursively on entire directory hierarchies. To update, select the files and/or directories you want, right click and select TortoiseSVNUpdate in the explorer context menu. A window will pop up displaying the progress of the update as it runs. Changes done by others will be merged into your files, keeping any changes you may have done to the same files. The repository is not affected by an update.

The progress dialog uses colour coding to highlight different update actions

Purple

New item added to your WC.

Dark red

Redundant item deleted from your WC, or missing item replaced in your WC.

Green

Changes from repository successfully merged with your local changes.

Bright red

Changes from repository merged with local changes, resulting in conflicts which you need to resolve.

Black

Unchanged item in your WC updated with newer version from the repository.

This is the default colour scheme, but you can customise those colours using the settings dialog. Read the section called “TortoiseSVN Colour Settings” for more information.

If you get any conflicts during an update (this can happen if others changed the same lines in the same file as you did and those changes don't match) then the dialog shows those conflicts in red. You can double click on these lines to start the external merge tool to resolve the conflicts.

When the update is complete, the progress dialog shows a summary of the number of items updated, added, removed, conflicted, etc. below the file list. This summary information can be copied to the clipboard using Ctrl+C.

The standard Update command has no options and just updates your working copy to the HEAD revision of the repository, which is the most common use case. If you want more control over the update process, you should use TortoiseSVNUpdate to Revision... instead. This allows you to update your working copy to a specific revision, not only to the most recent one. Suppose your working copy is at revision 100, but you want it to reflect the state which it had in revision 50 - then simply update to revision 50. In the same dialog you can also choose the depth at which to update the current folder. The terms used are described in the section called “Checkout Depth”. The default depth is Working copy, which preserves the existing depth setting. You can also choose whether to ignore any external projects in the update (i.e. projects referenced using svn:externals).

Caution

If you update a file or folder to a specific revision, you should not make changes to those files. You will get “out of date” error messages when you try to commit them! If you want to undo changes to a file and start afresh from an earlier revision, you can rollback to a previous revision from the revision log dialog. Take a look at the section called “Roll back (Undo) revisions in the repository” for further instructions, and alternative methods.

Update to Revision can occasionally be useful to see what your project looked like at some earlier point in its history. But in general, updating individual files to an earlier revision is not a good idea as it leaves your working copy in an inconsistent state. If the file you are updating has changed name, you may even find that the file just disappears from your working copy because no file of that name existed in the earlier revision. You should also note that the item will show a normal green overlay, so it is indistinguishable from files which are up-to-date.

If you simply want a local copy of an old version of a file it is better to use the Context MenuSave revision to... command from the log dialog for that file.

Multiple Files/Folders

If you select multiple files and folders in the explorer and then select Update, all of those files/folders are updated one by one. TortoiseSVN makes sure that all files/folders which are from the same repository are updated to the exact same revision! Even if between those updates another commit occurred.

Local File Already Exists

Sometimes when you try to update, the update fails with a message to say that there is already a local file of the same name. This typically happens when Subversion tries to checkout a newly versioned file, and finds that an unversioned file of the same name already exists in your working folder. Subversion will never overwrite an unversioned file - it might contain something you are working on, which coincidentally has the same filename as another developer has used for his newly committed file.

If you get this error message, the solution is simply to rename the local unversioned file. After completing the update, you can check whether the renamed file is still needed.

If you keep getting error messages, use TortoiseSVNCheck for Modifications instead to list all the problem files. That way you can deal with them all at once.

Resolving Conflicts

Once in a while, you will get a conflict when you update/merge your files from the repository or when you switch your working copy to a different URL. There are two kinds of conflicts:

file conflicts

A file conflict occurs if two (or more) developers have changed the same few lines of a file.

tree conflicts

A tree conflict occurs when a developer moved/renamed/deleted a file or folder, which another developer either also has moved/renamed/deleted or just modified.

File Conflicts

A file conflict occurs when two or more developers have changed the same few lines of a file. As Subversion knows nothing of your project, it leaves resolving the conflicts to the developers. Whenever a conflict is reported, you should open the file in question, and search for lines starting with the string <<<<<<<. The conflicting area is marked like this:

	<<<<<<< filename
		your changes
	=======
		code merged from repository
	>>>>>>> revision
	

Also, for every conflicted file Subversion places three additional files in your directory:

filename.ext.mine

This is your file as it existed in your working copy before you updated your working copy - that is, without conflict markers. This file has your latest changes in it and nothing else.

filename.ext.rOLDREV

This is the file that was the BASE revision before you updated your working copy. That is, it the file that you checked out before you made your latest edits.

filename.ext.rNEWREV

This is the file that your Subversion client just received from the server when you updated your working copy. This file corresponds to the HEAD revision of the repository.

You can either launch an external merge tool / conflict editor with TortoiseSVNEdit Conflicts or you can use any other editor to manually resolve the conflict. You should decide what the code should look like, do the necessary changes and save the file.

Afterwards execute the command TortoiseSVNResolved and commit your modifications to the repository. Please note that the Resolve command does not really resolve the conflict. It just removes the filename.ext.mine and filename.ext.r* files, to allow you to commit your changes.

If you have conflicts with binary files, Subversion does not attempt to merge the files itself. The local file remains unchanged (exactly as you last changed it) and you have filename.ext.r* files. If you want to discard your changes and keep the repository version, just use the Revert command. If you want to keep your version and overwrite the repository version, use the Resolved command, then commit your version.

You can use the Resolved command for multiple files if you right click on the parent folder and select TortoiseSVNResolved... This will bring up a dialog listing all conflicted files in that folder, and you can select which ones to mark as resolved.

Tree Conflicts

A tree conflict occurs when a developer moved/renamed/deleted a file or folder, which another developer either also has moved/renamed/deleted or just modified. There are many different situations that can result in a tree conflict, and all of them require different steps to resolve the conflict.

When a file is deleted locally in Subversion, the file is also deleted from the local file system, so even if it is part of a tree conflict it cannot show a conflicted overlay and you cannot right click on it to resolve the conflict. Use the Check for Modifications dialog instead to access the Edit conflicts option.

TortoiseSVN can help find the right place to merge changes, but there may be additional work required to sort out the conflicts. Remember that after an update the working BASE will always contain the revision of each item as it was in the repository at the time of update. If you revert a change after updating it goes back to the repository state, not to the way it was when you started making your own local changes.

Local delete, incoming edit upon update

  1. Developer A modifies Foo.c and commits it to the repository

  2. Developer B has simultaneously moved Foo.c to Bar.c in his working copy, or simply deleted Foo.c or its parent folder.

An update of developer B's working copy results in a tree conflict:

  • Foo.c has been deleted from working copy, but is marked with a tree conflict.

  • If the conflict results from a rename rather than a delete then Bar.c is marked as added, but does not contain developer A's modifications.

Developer B now has to choose whether to keep Developer A's changes. In the case of a file rename, he can merge the changes to Foo.c into the renamed file Bar.c. For simple file or directory deletions he can choose to keep the item with Developer A's changes and discard the deletion. Or, by marking the conflict as resolved without doing anything he effectively discards Developer A's changes.

The conflict edit dialog offers to merge changes if it can find the original file of the renamed Bar.c. Depending on where the update was invoked, it may not be possible to find the source file.

Local edit, incoming delete upon update

  1. Developer A moves Foo.c to Bar.c and commits it to the repository.

  2. Developer B modifies Foo.c in his working copy.

Or in the case of a folder move ...

  1. Developer A moves parent folder FooFolder to BarFolder and commits it to the repository.

  2. Developer B modifies Foo.c in his working copy.

An update of developer B's working copy results in a tree conflict. For a simple file conflict:

  • Bar.c is added to the working copy as a normal file.

  • Foo.c is marked as added (with history) and has a tree conflict.

For a folder conflict:

  • BarFolder is added to the working copy as a normal folder.

  • FooFolder is marked as added (with history) and has a tree conflict.

    Foo.c is marked as modified.

Developer B now has to decide whether to go with developer A's reorganisation and merge her changes into the corresponding file in the new structure, or simply revert A's changes and keep the local file.

To merge her local changes with the reshuffle, Developer B must first find out to what filename the conflicted file Foo.c was renamed/moved in the repository. This can be done by using the log dialog. The changes must then be merged by hand as there is currently no way to automate or even simplify this process. Once the changes have been ported across, the conflicted path is redundant and can be deleted. In this case use the Remove button in the conflict editor dialog to clean up and mark the conflict as resolved.

If Developer B decides that A's changes were wrong then she must choose the Keep button in the conflict editor dialog. This marks the conflicted file/folder as resolved, but Developer A's changes need to be removed by hand. Again the log dialog helps to track down what was moved.

Local delete, incoming delete upon update

  1. Developer A moves Foo.c to Bar.c and commits it to the repository

  2. Developer B moves Foo.c to Bix.c

An update of developer B's working copy results in a tree conflict:

  • Bix.c is marked as added with history.

  • Bar.c is added to the working copy with status 'normal'.

  • Foo.c is marked as deleted and has a tree conflict.

To resolve this conflict, Developer B has to find out to what filename the conflicted file Foo.c was renamed/moved in the repository. This can be done by using the log dialog.

Then developer B has to decide which new filename of Foo.c to keep - the one done by developer A or the rename done by himself.

After developer B has manually resolved the conflict, the tree conflict has to be marked as resolved with the button in the conflict editor dialog.

Local missing, incoming edit upon merge

  1. Developer A working on trunk modifies Foo.c and commits it to the repository

  2. Developer B working on a branch moves Foo.c to Bar.c and commits it to the repository

A merge of developer A's trunk changes to developer B's branch working copy results in a tree conflict:

  • Bar.c is already in the working copy with status 'normal'.

  • Foo.c is marked as missing with a tree conflict.

To resolve this conflict, Developer B has to mark the file as resolved in the conflict editor dialog, which will remove it from the conflict list. She then has to decide whether to copy the missing file Foo.c from the repository to the working copy, whether to merge Developer A's changes to Foo.c into the renamed Bar.c or whether to ignore the changes by marking the conflict as resolved and doing nothing else.

Note that if you copy the missing file from the repository and then mark as resolved, your copy will be removed again. You have to resolve the conflict first.

Local edit, incoming delete upon merge

  1. Developer A working on trunk moves Foo.c to Bar.c and commits it to the repository

  2. Developer B working on a branch modifies Foo.c and commits it to the repository.

There is an equivalent case for folder moves, but it is not yet detected in Subversion 1.6 ...

  1. Developer A working on trunk moves parent folder FooFolder to BarFolder and commits it to the repository.

  2. Developer B working on a branch modifies Foo.c in her working copy.

A merge of developer A's trunk changes to developer B's branch working copy results in a tree conflict:

  • Bar.c is marked as added.

  • Foo.c is marked as modified with a tree conflict.

Developer B now has to decide whether to go with developer A's reorganisation and merge her changes into the corresponding file in the new structure, or simply revert A's changes and keep the local file.

To merge her local changes with the reshuffle, Developer B must first find out to what filename the conflicted file Foo.c was renamed/moved in the repository. This can be done by using the log dialog for the merge source. The conflict editor only shows the log for the working copy as it does not know which path was used in the merge, so you will have to find that yourself. The changes must then be merged by hand as there is currently no way to automate or even simplify this process. Once the changes have been ported across, the conflicted path is redundant and can be deleted. In this case use the Remove button in the conflict editor dialog to clean up and mark the conflict as resolved.

If Developer B decides that A's changes were wrong then she must choose the Keep button in the conflict editor dialog. This marks the conflicted file/folder as resolved, but Developer A's changes need to be removed by hand. Again the log dialog for the merge source helps to track down what was moved.

Local delete, incoming delete upon merge

  1. Developer A working on trunk moves Foo.c to Bar.c and commits it to the repository

  2. Developer B working on a branch moves Foo.c to Bix.c and commits it to the repository

A merge of developer A's trunk changes to developer B's branch working copy results in a tree conflict:

  • Bix.c is marked with normal (unmodified) status.

  • Bar.c is marked as added with history.

  • Foo.c is marked as missing and has a tree conflict.

To resolve this conflict, Developer B has to find out to what filename the conflicted file Foo.c was renamed/moved in the repository. This can be done by using the log dialog for the merge source. The conflict editor only shows the log for the working copy as it does not know which path was used in the merge, so you will have to find that yourself.

Then developer B has to decide which new filename of Foo.c to keep - the one done by developer A or the rename done by himself.

After developer B has manually resolved the conflict, the tree conflict has to be marked as resolved with the button in the conflict editor dialog.

Other tree conflicts

There are other cases which are labelled as tree conflicts simply because the conflict involves a folder rather than a file. For example if you add a folder with the same name to both trunk and branch and then try to merge you will get a tree conflict. If you want to keep the folder from the merge target, just mark the conflict as resolved. If you want to use the one in the merge source then you need to SVN delete the one in the target first and run the merge again. If you need anything more complicated then you have to resolve manually.

Getting Status Information

While you are working on your working copy you often need to know which files you have changed/added/removed or renamed, or even which files got changed and committed by others.

Icon Overlays

Figure 4.12. Explorer showing icon overlays

Explorer showing icon overlays


Now that you have checked out a working copy from a Subversion repository you can see your files in the windows explorer with changed icons. This is one of the reasons why TortoiseSVN is so popular. TortoiseSVN adds a so called overlay icon to each file icon which overlaps the original file icon. Depending on the Subversion status of the file the overlay icon is different.

A fresh checked out working copy has a green checkmark as overlay. That means the Subversion status is normal.

As soon as you start editing a file, the status changes to modified and the icon overlay then changes to a red exclamation mark. That way you can easily see which files were changed since you last updated your working copy and need to be committed.

If during an update a conflict occurs then the icon changes to a yellow exclamation mark.

If you have set the svn:needs-lock property on a file, Subversion makes that file read-only until you get a lock on that file. Such files have this overlay to indicate that you have to get a lock first before you can edit that file.

If you hold a lock on a file, and the Subversion status is normal, this icon overlay reminds you that you should release the lock if you are not using it to allow others to commit their changes to the file.

This icon shows you that some files or folders inside the current folder have been scheduled to be deleted from version control or a file under version control is missing in a folder.

The plus sign tells you that a file or folder has been scheduled to be added to version control.

The bar sign tells you that a file or folder is ignored for version control purposes. This overlay is optional.

This icon shows files and folders which are not under version control, but have not been ignored. This overlay is optional.

In fact, you may find that not all of these icons are used on your system. This is because the number of overlays allowed by Windows is very limited and if you are also using an old version of TortoiseCVS, then there are not enough overlay slots available. TortoiseSVN tries to be a “Good Citizen (TM)” and limits its use of overlays to give other apps a chance too.

Now that there are more Tortoise clients around (TortoiseCVS, TortoiseHG, ...) the icon limit becomes a real problem. To work around this, the TortoiseSVN project introduced a common shared icon set, loaded as a DLL, which can be used by all Tortoise clients. Check with your client provider to see if this has been integrated yet :-)

For a description of how icon overlays correspond to Subversion status and other technical details, read the section called “Icon Overlays”.

TortoiseSVN Columns In Windows Explorer

The same information which is available from the icon overlays (and much more) can be displayed as additional columns in Windows Explorer's Details View.

Simply right click on one of the headings of a column, choose More... from the context menu displayed. A dialog will appear where you can specify the columns and their order, which is displayed in the “Detailed View”. Scroll down until the entries starting with SVN come into view. Check the ones you would like to have displayed and close the dialog by pressing OK. The columns will be appended to the right of those currently displayed. You can reorder them by drag and drop, or resize them, so that they fit your needs.

Important

The additional columns in the Windows Explorer are not available on Vista, since Microsoft decided to not allow such columns for all files anymore but only for specific file types.

Tip

If you want the current layout to be displayed in all your working copies, you may want to make this the default view.

Local and Remote Status

Figure 4.13. Check for Modifications

Check for Modifications


It's often very useful to know which files you have changed and also which files got changed and committed by others. That's where the command TortoiseSVNCheck For Modifications... comes in handy. This dialog will show you every file that has changed in any way in your working copy, as well as any unversioned files you may have.

If you click on the Check Repository then you can also look for changes in the repository. That way you can check before an update if there's a possible conflict. You can also update selected files from the repository without updating the whole folder. By default, the Check Repository button only fetches the remote status with the checkout depth of the working copy. If you want to see all files and folders in the repository, even those you have not checked out, then you have to hold down the Shift key when you click on the Check Repository button.

The dialog uses colour coding to highlight the status.

Blue

Locally modified items.

Purple

Added items. Items which have been added with history have a + sign in the Text status column, and a tooltip shows where the item was copied from.

Dark red

Deleted or missing items.

Green

Items modified locally and in the repository. The changes will be merged on update. These may produce conflicts on update.

Bright red

Items modified locally and deleted in repository, or modified in repository and deleted locally. These will produce conflicts on update.

Black

Unchanged and unversioned items.

This is the default colour scheme, but you can customise those colours using the settings dialog. Read the section called “TortoiseSVN Colour Settings” for more information.

Items which have been switched to a different repository path are also indicated using an (s) marker. You may have switched something while working on a branch and forgotten to switch back to trunk. This is your warning sign!

From the context menu of the dialog you can show a diff of the changes. Check the local changes you made using Context MenuCompare with Base. Check the changes in the repository made by others using Context MenuShow Differences as Unified Diff.

You can also revert changes in individual files. If you have deleted a file accidentally, it will show up as Missing and you can use Revert to recover it.

Unversioned and ignored files can be sent to the recycle bin from here using Context MenuDelete. If you want to delete files permanently (bypassing the recycle bin) hold the Shift key while clicking on Delete.

If you want to examine a file in detail, you can drag it from here into another application such as a text editor or IDE.

The columns are customizable. If you right click on any column header you will see a context menu allowing you to select which columns are displayed. You can also change column width by using the drag handle which appears when you move the mouse over a column boundary. These customizations are preserved, so you will see the same headings next time.

If you are working on several unrelated tasks at once, you can also group files together into changelists. Read the section called “Change Lists” for more information.

At the bottom of the dialog you can see a summary of the range of repository revisions in use in your working copy. These are the commit revisions, not the update revisions; they represent the range of revisions where these files were last committed, not the revisions to which they have been updated. Note that the revision range shown applies only to the items displayed, not to the entire working copy. If you want to see that information for the whole working copy you must check the Show unmodified files checkbox.

Tip

If you want a flat view of your working copy, i.e. showing all files and folders at every level of the folder hierarchy, then the Check for Modifications dialog is the easiest way to achieve that. Just check the Show unmodified files checkbox to show all files in your working copy.

Repairing External Renames

Sometimes files get renamed outside of Subversion, and they show up in the file list as a missing file and an unversioned file. To avoid losing the history you need to notify Subversion about the connection. Simply select both the old name (missing) and the new name (unversioned) and use Context MenuRepair Move to pair the two files as a rename.

Repairing External Copies

If you made a copy of a file but forgot to use the Subversion command to do so, you can repair that copy so the new file doesn't lose its history. Simply select both the old name (normal or modified) and the new name (unversioned) and use Context MenuRepair Copy to pair the two files as a copy.

Viewing Diffs

Often you want to look inside your files, to have a look at what you've changed. You can accomplish this by selecting a file which has changed, and selecting Diff from TortoiseSVN's context menu. This starts the external diff-viewer, which will then compare the current file with the pristine copy (BASE revision), which was stored after the last checkout or update.

Tip

Even when not inside a working copy or when you have multiple versions of the file lying around, you can still display diffs:

Select the two files you want to compare in explorer (e.g. using Ctrl and the mouse) and choose Diff from TortoiseSVN's context menu. The file clicked last (the one with the focus, i.e. the dotted rectangle) will be regarded as the later one.

Change Lists

In an ideal world, you only ever work on one thing at a time, and your working copy contains only one set of logical changes. OK, back to reality. It often happens that you have to work on several unrelated tasks at once, and when you look in the commit dialog, all the changes are mixed in together. The changelist feature helps you group files together, making it easier to see what you are doing. Of course this can only work if the changes do not overlap. If two different tasks affect the same file, there is no way to separate the changes.

Important

The changelist feature in TortoiseSVN is only available in Windows XP and later, as it depends on a shell capability which is not present in Windows 2000. Sorry, but Win2K is really quite old now, so please don't complain.

You can see changelists in several places, but the most important ones are the commit dialog and the check-for-modifications dialog. Let's start in the check-for-modifications dialog after you have worked on several features and many files. When you first open the dialog, all the changed files are listed together. Suppose you now want to organise things and group those files according to feature.

Select one or more files and use Context MenuMove to changelist to add an item to a changelist. Initially there will be no changelists, so the first time you do this you will create a new changelist. Give it name which describes what you are using it for, and click OK. The dialog will now change to show groups of items.

Once you have created a changelist you can drag and drop items into it, either from another changelist, or from Windows Explorer. Dragging from Explorer can be useful as it allows you to add items to a changelist before the file is modified. You could do that from the check-for-modifications dialog, but only by displaying all unmodified files.

Figure 4.14. Commit dialog with Changelists

Commit dialog with Changelists


In the commit dialog you can see those same files, grouped by changelist. Apart from giving an immediate visual indication of groupings, you can also use the group headings to select which files to commit.

On XP, there is a context menu when you right click on a group heading which gives you the choice to check or uncheck all group entries. On Vista however the context menu is not necessary. Click on the group header to select all entries, then check one of the selected entries to check all.

TortoiseSVN reserves one changelist name for its own use, namely ignore-on-commit. This is used to mark versioned files which you almost never want to commit even though they have local changes. This feature is described in the section called “Excluding Items from the Commit List”.

When you commit files belonging to a changelist then normally you would expect that the changelist membership is no longer needed. So by default, files are removed from changelists automatically on commit. If you wish to retain the file in its changelist, use the Keep changelists checkbox at the bottom of the commit dialog.

Tip

Changelists are purely a local client feature. Creating and removing changelists will not affect the repository, nor anyone else's working copy. They are simply a convenient way for you to organise your files.

Revision Log Dialog

For every change you make and commit, you should provide a log message for that change. That way you can later find out what changes you made and why, and you have a detailed log for your development process.

The Revision Log Dialog retrieves all those log messages and shows them to you. The display is divided into 3 panes.

  • The top pane shows a list of revisions where changes to the file/folder have been committed. This summary includes the date and time, the person who committed the revision and the start of the log message.

    Lines shown in blue indicate that something has been copied to this development line (perhaps from a branch).

  • The middle pane shows the full log message for the selected revision.

  • The bottom pane shows a list of all files and folders that were changed as part of the selected revision.

But it does much more than that - it provides context menu commands which you can use to get even more information about the project history.

Invoking the Revision Log Dialog

Figure 4.15. The Revision Log Dialog

The Revision Log Dialog


There are several places from where you can show the Log dialog:

  • From the TortoiseSVN context submenu

  • From the property page

  • From the Progress dialog after an update has finished. Then the Log dialog only shows those revisions which were changed since your last update

If the repository is unavailable you will see the Want to go offline? dialog, described in the section called “Offline Mode”.

Revision Log Actions

The top pane has an Actions column containing icons that summarize what has been done in that revision. There are four different icons, each shown in its own column.

If a revision modified a file or directory, the modified icon is shown in the first column.

If a revision added a file or directory, the added icon is shown in the second column.

If a revision deleted a file or directory, the deleted icon is shown in the third column.

If a revision replaced a file or directory, the replaced icon is shown in the fourth column.

Getting Additional Information

Figure 4.16. The Revision Log Dialog Top Pane with Context Menu

The Revision Log Dialog Top Pane with Context Menu


The top pane of the Log dialog has a context menu that allows you to access much more information. Some of these menu entries appear only when the log is shown for a file, and some only when the log is shown for a folder.

Compare with working copy

Compare the selected revision with your working copy. The default Diff-Tool is TortoiseMerge which is supplied with TortoiseSVN. If the log dialog is for a folder, this will show you a list of changed files, and allow you to review the changes made to each file individually.

Compare and blame with working BASE

Blame the selected revision, and the file in your working BASE and compare the blame reports using a visual diff tool. Read the section called “Blame Differences” for more detail. (files only).

Show changes as unified diff

View the changes made in the selected revision as a Unified-Diff file (GNU patch format). This shows only the differences with a few lines of context. It is harder to read than a visual file compare, but will show all file changes together in a compact format.

Compare with previous revision

Compare the selected revision with the previous revision. This works in a similar manner to comparing with your working copy. For folders this option will first show the changed files dialog allowing you to select files to compare.

Compare and blame with previous revision

Show the changed files dialog allowing you to select files. Blame the selected revision, and the previous revision, and compare the results using a visual diff tool. (folders only).

Save revision to...

Save the selected revision to a file so you have an older version of that file. (files only).

Open / Open with...

Open the selected file, either with the default viewer for that file type, or with a program you choose. (files only).

Blame...

Blame the file up to the selected revision. (files only).

Browse repository

Open the repository browser to examine the selected file or folder in the repository as it was at the selected revision.

Create branch/tag from revision

Create a branch or tag from a selected revision. This is useful e.g. if you forgot to create a tag and already committed some changes which weren't supposed to get into that release.

Update item to revision

Update your working copy to the selected revision. Useful if you want to have your working copy reflect a time in the past, or if there have been further commits to the repository and you want to update your working copy one step at a time. It is best to update a whole directory in your working copy, not just one file, otherwise your working copy could be inconsistent.

If you want to undo an earlier change permanently, use Revert to this revision instead.

Revert to this revision

Revert to an earlier revision. If you have made several changes, and then decide that you really want to go back to how things were in revision N, this is the command you need. The changes are undone in your working copy so this operation does not affect the repository until you commit the changes. Note that this will undo all changes made after the selected revision, replacing the file/folder with the earlier version.

If your working copy is in an unmodified state, after you perform this action your working copy will show as modified. If you already have local changes, this command will merge the undo changes into your working copy.

What is happening internally is that Subversion performs a reverse merge of all the changes made after the selected revision, undoing the effect of those previous commits.

If after performing this action you decide that you want to undo the undo and get your working copy back to its previous unmodified state, you should use TortoiseSVNRevert from within Windows Explorer, which will discard the local modifications made by this reverse merge action.

If you simply want to see what a file or folder looked like at an earlier revision, use Update to revision or Save revision as... instead.

Revert changes from this revision

Undo changes from which were made in the selected revision. The changes are undone in your working copy so this operation does not affect the repository at all! Note that this will undo the changes made in that revision only; it does not replace your working copy with the entire file at the earlier revision. This is very useful for undoing an earlier change when other unrelated changes have been made since.

If your working copy is in an unmodified state, after you perform this action your working copy will show as modified. If you already have local changes, this command will merge the undo changes into your working copy.

What is happening internally is that Subversion performs a reverse merge of that one revision, undoing its effect from a previous commit.

You can undo the undo as described above in Revert to this revision.

Merge revision to...

Merge the selected revision(s) into a different working copy. A folder selection dialog allows you to choose the working copy to merge into, but after that there is no confirmation dialog, nor any opportunity to try a test merge. It is a good idea to merge into an unmodified working copy so that you can revert the changes if it doesn't work out! This is a useful feature if you want to merge selected revisions from one branch to another.

Checkout...

Make a fresh checkout of the selected folder at the selected revision. This brings up a dialog for you to confirm the URL and revision, and select a location for the checkout.

Export...

Export the selected file/folder at the selected revision. This brings up a dialog for you to confirm the URL and revision, and select a location for the export.

Edit author / log message

Edit the log message or author attached to a previous commit. Read the section called “Changing the Log Message and Author” to find out how this works.

Show revision properties

View and edit any revision property, not just log message and author. Refer to the section called “Changing the Log Message and Author”.

Copy to clipboard

Copy the log details of the selected revisions to the clipboard. This will copy the revision number, author, date, log message and the list of changed items for each revision.

Search log messages...

Search log messages for the text you enter. This searches the log messages that you entered and also the action summaries created by Subversion (shown in the bottom pane). The search is not case sensitive.

Figure 4.17. Top Pane Context Menu for 2 Selected Revisions

Top Pane Context Menu for 2 Selected Revisions


If you select two revisions at once (using the usual Ctrl-modifier), the context menu changes and gives you fewer options:

Compare revisions

Compare the two selected revisions using a visual difference tool. The default Diff-Tool is TortoiseMerge which is supplied with TortoiseSVN.

If you select this option for a folder, a further dialog pops up listing the changed files and offering you further diff options. Read more about the Compare Revisions dialog in the section called “Comparing Folders”.

Blame revisions

Blame the two revisions and compare the blame reports using a visual difference tool. Read the section called “Blame Differences” for more detail.

Show differences as unified diff

View the differences between the two selected revisions as a Unified-Diff file. This works for files and folders.

Copy to clipboard

Copy log messages to clipboard as described above.

Search log messages...

Search log messages as described above.

If you select two or more revisions (using the usual Ctrl or Shift modifiers), the context menu will include an entry to Revert all changes which were made in the selected revisions. This is the easiest way to rollback a group of revisions in one go.

You can also choose to merge the selected revisions to another working copy, as described above.

If all selected revisions have the same author, you can edit the author of all those revisions in one go.

Figure 4.18. The Log Dialog Bottom Pane with Context Menu

The Log Dialog Bottom Pane with Context Menu


The bottom pane of the Log dialog also has a context menu that allows you to

Show changes

Show changes made in the selected revision for the selected file.

Blame changes

Blame the selected revision and the previous revision for the selected file, and compare the blame reports using a visual diff tool. Read the section called “Blame Differences” for more detail.

Show as unified diff

Show file changes in unified diff format. This context menu is only available for files shown as modified.

Open / Open with...

Open the selected file, either with the default viewer for that file type, or with a program you choose.

Blame...

Opens the Blame dialog, allowing you to blame up to the selected revision.

Revert changes from this revision

Revert the changes made to the selected file in that revision.

Show properties

View the Subversion properties for the selected item.

Show log

Show the revision log for the selected single file.

Get merge logs

Show the revision log for the selected single file, including merged changes. Find out more in the section called “Merge Tracking Features”.

Save revision to...

Save the selected revision to a file so you have an older version of that file.

Tip

You may notice that sometimes we refer to changes and other times to differences. What's the difference?

Subversion uses revision numbers to mean 2 different things. A revision generally represents the state of the repository at a point in time, but it can also be used to represent the changeset which created that revision, eg. “Done in r1234” means that the changes committed in r1234 implement feature X. To make it clearer which sense is being used, we use two different terms.

If you select two revisions N and M, the context menu will offer to show the difference between those two revisions. In Subversion terms this is diff -r M:N.

If you select a single revision N, the context menu will offer to show the changes made in that revision. In Subversion terms this is diff -r N-1:N or diff -c N.

The bottom pane shows the files changed in all selected revisions, so the context menu always offers to show changes.

Getting more log messages

The Log dialog does not always show all changes ever made for a number of reasons:

  • For a large repository there may be hundreds or even thousands of changes and fetching them all could take a long time. Normally you are only interested in the more recent changes. By default, the number of log messages fetched is limited to 100, but you can change this value in TortoiseSVNSettings (the section called “TortoiseSVN Dialog Settings 1”),

  • When the Stop on copy/rename box is checked, Show Log will stop at the point that the selected file or folder was copied from somewhere else within the repository. This can be useful when looking at branches (or tags) as it stops at the root of that branch, and gives a quick indication of changes made in that branch only.

    Normally you will want to leave this option unchecked. TortoiseSVN remembers the state of the checkbox, so it will respect your preference.

    When the Show Log dialog is invoked from within the Merge dialog, the box is always checked by default. This is because merging is most often looking at changes on branches, and going back beyond the root of the branch does not make sense in that instance.

    Note that Subversion currently implements renaming as a copy/delete pair, so renaming a file or folder will also cause the log display to stop if this option is checked.

If you want to see more log messages, click the Next 100 to retrieve the next 100 log messages. You can repeat this as many times as needed.

Next to this button there is a multi-function button which remembers the last option you used it for. Click on the arrow to see the other options offered.

Use Show Range ... if you want to view a specific range of revisions. A dialog will then prompt you to enter the start and end revision.

Use Show All if you want to see all log messages from HEAD right back to revision 1.

Current Working Copy Revision

Because the log dialog shows you the log from HEAD, not from the current working copy revision, it often happens that there are log messages shown for content which has not yet been updated in your working copy. To help make this clearer, the commit message which corresponds to the revision you have in your working copy is shown in bold.

When you show the log for a folder the revision highlighted is the highest revision found anywhere within that folder, which requires a crawl of the working copy. The crawl takes place within a separate thread so as not to delay showing the log, but as a result highlighting for folders may not appear immediately.

Merge Tracking Features

Subversion 1.5 and later keeps a record of merges using properties. This allows us to get a more detailed history of merged changes. For example, if you develop a new feature on a branch and then merge that branch back to trunk, the feature development will show up on the trunk log as a single commit for the merge, even though there may have been 1000 commits during branch development.

Figure 4.19. The Log Dialog Showing Merge Tracking Revisions

The Log Dialog Showing Merge Tracking Revisions

If you want to see the detail of which revisions were merged as part of that commit, use the Include merged revisions checkbox. This will fetch the log messages again, but will also interleave the log messages from revisions which were merged. Merged revisions are shown in grey because they represent changes made on a different part of the tree.

Of course, merging is never simple! During feature development on the branch there will probably be occasional merges back from trunk to keep the branch in sync with the main line code. So the merge history of the branch will also include another layer of merge history. These different layers are shown in the log dialog using indentation levels.

Changing the Log Message and Author

Revision properties are completely different from the Subversion properties of each item. Revprops are descriptive items which are associated with one specific revision number in the repository, such as log message, commit date and committer name (author).

Sometimes you might want to change a log message you once entered, maybe because there's a spelling error in it or you want to improve the message or change it for other reasons. Or you want to change the author of the commit because you forgot to set up authentication or...

Subversion lets you change revision properties any time you want. But since such changes can't be undone (those changes are not versioned) this feature is disabled by default. To make this work, you must set up a pre-revprop-change hook. Please refer to the chapter on Hook Scripts in the Subversion Book for details about how to do that. Read the section called “Server side hook scripts” to find some further notes on implementing hooks on a Windows machine.

Once you've set up your server with the required hooks, you can change the author and log message (or any other revprop) of any revision, using the context menu from the top pane of the Log dialog. You can also edit a log message using the context menu for the middle pane.

Warning

Because Subversion's revision properties are not versioned, making modifications to such a property (for example, the svn:log commit message property) will overwrite the previous value of that property forever.

Filtering Log Messages

If you want to restrict the log messages to show only those you are interested in rather than scrolling through a list of hundreds, you can use the filter controls at the top of the Log Dialog. The start and end date controls allow you to restrict the output to a known date range. The search box allows you to show only messages which contain a particular phrase.

Click on the search icon to select which information you want to search in, and to choose regex mode. Normally you will only need a simple sub-string search, but if you need to more flexible search terms, you can use regular expressions. If you hover the mouse over the box, a tooltip will give hints on how to use the regex functions, or the sub-string functions. The filter works by checking whether your filter string matches the log entries, and then only those entries which match the filter string are shown.

Simple sub-string search works in a manner similar to a search engine. Strings to search for are separated by spaces, and all strings must match. You can use a leading - to specify that a particular sub-string is not found (invert matching for that term), and you can use ! at the start of the expression to invert matching for the entire expression. You can use quote marks to surround a string which must contain spaces, and if you want to search for a literal quotation mark you can use two quotation marks together as a self-escaping sequence. Note that the backslash character is not used as an escape character and has no special significance in simple sub-string searches. Examples will make this easier:

Alice Bob -Eve

searches for strings containing both Alice and Bob but not Eve

!Alice Bob

searches for strings which do not contain both Alice and Bob

!-Alice -Bob

do you remember De Morgan's theorem? NOT(NOT Alice AND NOT Bob) reduces to (Alice OR Bob).

"Alice and Bob"

searches for the literal expression “Alice and Bob

""

searches for a double-quote anywhere in the text

"Alice says ""hi"" to Bob"

searches for the literal expression “Alice says "hi" to Bob

Describing the use of regular expression searches is beyond the scope of this manual, but you can find online documentation and a tutorial at http://www.regular-expressions.info/ .

Note that these filters act on the messages already retrieved. They do not control downloading of messages from the repository.

You can also filter the path names in the bottom pane using the Show only affected paths checkbox. Affected paths are those which contain the path used to display the log. If you fetch the log for a folder, that means anything in that folder or below it. For a file it means just that one file. Normally the path list shows any other paths which are affected by the same commit, but in grey. If the box is checked, those paths are hidden.

Sometimes your working practices will require log messages to follow a particular format, which means that the text describing the changes is not visible in the abbreviated summary shown in the top pane. The property tsvn:logsummary can be used to extract a portion of the log message to be shown in the top pane. Read the section called “TortoiseSVN Project Properties” to find out how to use this property.

No Log Formatting from Repository Browser

Because the formatting depends upon accessing subversion properties, you will only see the results when using a checked out working copy. Fetching properties remotely is a slow operation, so you will not see this feature in action from the repo browser.

Statistical Information

The Statistics button brings up a box showing some interesting information about the revisions shown in the Log dialog. This shows how many authors have been at work, how many commits they have made, progress by week, and much more. Now you can see at a glance who has been working hardest and who is slacking ;-)

Statistics Page

This page gives you all the numbers you can think of, in particular the period and number of revisions covered, and some min/max/average values.

Commits by Author Page

Figure 4.20. Commits-by-Author Histogram

Commits-by-Author Histogram


This graph shows you which authors have been active on the project as a simple histogram, stacked histogram or pie chart.

Figure 4.21. Commits-by-Author Pie Chart

Commits-by-Author Pie Chart


Where there are a few major authors and many minor contributors, the number of tiny segments can make the graph more difficult to read. The slider at the bottom allows you to set a threshold (as a percentage of total commits) below which any activity is grouped into an Others category.

Commits by date Page

Figure 4.22. Commits-by-date Graph

Commits-by-date Graph


This page gives you a graphical representation of project activity in terms of number of commits and author. This gives some idea of when a project is being worked on, and who was working at which time.

When there are several authors, you will get many lines on the graph. There are two views available here: normal, where each author's activity is relative to the base line, and stacked, where each author's activity is relative to the line underneath. The latter option avoids the lines crossing over, which can make the graph easier to read, but less easy to see one author's output.

By default the analysis is case-sensitive, so users PeterEgan and PeteRegan are treated as different authors. However, in many cases user names are not case-sensitive, and are sometimes entered inconsistently, so you may want DavidMorgan and davidmorgan to be treated as the same person. Use the Authors case insensitive checkbox to control how this is handled.

Note that the statistics cover the same period as the Log dialog. If that is only displaying one revision then the statistics will not tell you very much.

Offline Mode

Figure 4.23. Go Offline Dialog

Go Offline Dialog


If the server is not reachable, and you have log caching enabled you can use the log dialog and revision graph in offline mode. This uses data from the cache, which allows you to continue working although the information may not be up-to-date or even complete.

Here you have three options:

Offline for now

Complete the current operation in offline mode, but retry the repository next time log data is requested.

Permanently offline

Remain in offline mode until a repository check is specifically requested. See the section called “Refreshing the View”.

Cancel

If you don't want to continue the operation with possibly stale data, just cancel.

The Make this the default checkbox prevents this dialog from re-appearing and always picks the option you choose next. You can still change (or remove) the default after doing this from TortoiseSVNSettings.

Refreshing the View

If you want to check the server again for newer log messages, you can simply refresh the view using F5. If you are using the log cache (enabled by default), this will check the repository for newer messages and fetch only the new ones. If the log cache was in offline mode, this will also attempt to go back online.

If you are using the log cache and you think the message content or author may have changed, you can use Shift-F5 or Ctrl-F5 to re-fetch the displayed messages from the server and update the log cache. Note that this only affects messages currently shown and does not invalidate the entire cache for that repository.

Viewing Differences

One of the commonest requirements in project development is to see what has changed. You might want to look at the differences between two revisions of the same file, or the differences between two separate files. TortoiseSVN provides a built-in tool named TortoiseMerge for viewing differences of text files. For viewing differences of image files, TortoiseSVN also has a tool named TortoiseIDiff. Of course, you can use your own favourite diff program if you like.

File Differences

Local changes

If you want to see what changes you have made in your working copy, just use the explorer context menu and select TortoiseSVNDiff.

Difference to another branch/tag

If you want to see what has changed on trunk (if you are working on a branch) or on a specific branch (if you are working on trunk), you can use the explorer context menu. Just hold down the Shift key while you right click on the file. Then select TortoiseSVNDiff with URL. In the following dialog, specify the URL in the repository with which you want to compare your local file to.

You can also use the repository browser and select two trees to diff, perhaps two tags, or a branch/tag and trunk. The context menu there allows you to compare them using Compare revisions. Read more in the section called “Comparing Folders”.

Difference from a previous revision

If you want to see the difference between a particular revision and your working copy, use the Revision Log dialog, select the revision of interest, then select Compare with working copy from the context menu.

If you want to see the difference between the last committed revision and your working copy, assuming that the working copy hasn't been modified, just right click on the file. Then select TortoiseSVNDiff with previous version. This will perform a diff between the revision before the last-commit-date (as recorded in your working copy) and the working BASE. This shows you the last change made to that file to bring it to the state you now see in your working copy. It will not show changes newer than your working copy.

Difference between two previous revisions

If you want to see the difference between two revisions which are already committed, use the Revision Log dialog and select the two revisions you want to compare (using the usual Ctrl-modifier). Then select Compare revisions from the context menu.

If you did this from the revision log for a folder, a Compare Revisions dialog appears, showing a list of changed files in that folder. Read more in the section called “Comparing Folders”.

All changes made in a commit

If you want to see the changes made to all files in a particular revision in one view, you can use Unified-Diff output (GNU patch format). This shows only the differences with a few lines of context. It is harder to read than a visual file compare, but will show all the changes together. From the Revision Log dialog select the revision of interest, then select Show Differences as Unified-Diff from the context menu.

Difference between files

If you want to see the differences between two different files, you can do that directly in explorer by selecting both files (using the usual Ctrl-modifier). Then from the explorer context menu select TortoiseSVNDiff.

Difference between WC file/folder and a URL

If you want to see the differences between a file in your working copy, and a file in any Subversion repository, you can do that directly in explorer by selecting the file then holding down the Shift key whilst right clicking to obtain the context menu. Select TortoiseSVNDiff with URL. You can do the same thing for a working copy folder. TortoiseMerge shows these differences in the same way as it shows a patch file - a list of changed files which you can view one at a time.

Difference with blame information

If you want to see not only the differences but also the author, revision and date that changes were made, you can combine the diff and blame reports from within the revision log dialog. Read the section called “Blame Differences” for more detail.

Difference between folders

The built-in tools supplied with TortoiseSVN do not support viewing differences between directory hierarchies. But if you have an external tool which does support that feature, you can use that instead. In the section called “External Diff/Merge Tools” we tell you about some tools which we have used.

If you have configured a third party diff tool, you can use Shift when selecting the Diff command to use the alternate tool. Read the section called “External Program Settings” to find out about configuring other diff tools.

Line-end and Whitespace Options

Sometimes in the life of a project you might change the line endings from CRLF to LF, or you may change the indentation of a section. Unfortunately this will mark a large number of lines as changed, even though there is no change to the meaning of the code. The options here will help to manage these changes when it comes to comparing and applying differences. You will see these settings in the Merge and Blame dialogs, as well as in the settings for TortoiseMerge.

Ignore line endings excludes changes which are due solely to difference in line-end style.

Compare whitespaces includes all changes in indentation and inline whitespace as added/removed lines.

Ignore whitespace changes excludes changes which are due solely to a change in the amount or type of whitespace, eg. changing the indentation or changing tabs to spaces. Adding whitespace where there was none before, or removing a whitespace completely is still shown as a change.

Ignore all whitespaces excludes all whitespace-only changes.

Naturally, any line with changed content is always included in the diff.

Comparing Folders

Figure 4.24. The Compare Revisions Dialog

The Compare Revisions Dialog


When you select two trees within the repository browser, or when you select two revisions of a folder in the log dialog, you can Context menuCompare revisions.

This dialog shows a list of all files which have changed and allows you to compare or blame them individually using context menu.

You can export a change tree, which is useful if you need to send someone else your project tree structure, but containing only the files which have changed. This operation works on the selected files only, so you need to select the files of interest - usually that means all of them - and then Context menuExport selection to.... You will be prompted for a location to save the change tree.

You can also export the list of changed files to a text file using Context menuSave list of selected files to....

If you want to export the list of files and the actions (modified, added, deleted) as well, you can do that using Context menuCopy selection to clipboard.

The button at the top allows you to change the direction of comparison. You can show the changes need to get from A to B, or if you prefer, from B to A.

The buttons with the revision numbers on can be used to change to a different revision range. When you change the range, the list of items which differ between the two revisions will be updated automatically.

If the list of filenames is very long, you can use the search box to reduce the list to filenames containing specific text. Note that a simple text search is used, so if you want to restrict the list to C source files you should enter .c rather than *.c.

Diffing Images Using TortoiseIDiff

There are many tools available for diffing text files, including our own TortoiseMerge, but we often find ourselves wanting to see how an image file has changed too. That's why we created TortoiseIDiff.

Figure 4.25. The image difference viewer

The image difference viewer


TortoiseSVNDiff for any of the common image file formats will start TortoiseIDiff to show image differences. By default the images are displayed side-by-side but you can use the View menu or toolbar to switch to a top-bottom view instead, or if you prefer, you can overlay the images and pretend you are using a lightbox.

Naturally you can also zoom in and out and pan around the image. You can also pan the image simply by left-dragging it. If you select the Link images together option, then the pan controls (scrollbars, mousewheel) on both images are linked.

An image info box shows details about the image file, such as the size in pixels, resolution and colour depth. If this box gets in the way, use ViewImage Info to hide it. You can get the same information in a tooltip if you hover the mouse over the image title bar.

When the images are overlaid, the relative intensity of the images (alpha blend) is controlled by a slider control at the left side. You can click anywhere in the slider to set the blend directly, or you can drag the slider to change the blend interactively. Ctrl+Shift-Wheel to change the blend.

The button above the slider toggles between 0% and 100% blends, and if you double click the button, the blend toggles automatically every second until you click the button again. This can be useful when looking for multiple small changes.

Sometimes you want to see a difference rather than a blend. You might have the image files for two revisions of a printed circuit board and want to see which tracks have changed. If you disable alpha blend mode, the difference will be shown as an XOR of the pixel colour values. Unchanged areas will be plain white and changes will be coloured.

External Diff/Merge Tools

If the tools we provide don't do what you need, try one of the many open-source or commercial programs available. Everyone has their own favourites, and this list is by no means complete, but here are a few that you might consider:

WinMerge

WinMerge is a great open-source diff tool which can also handle directories.

Perforce Merge

Perforce is a commercial RCS, but you can download the diff/merge tool for free. Get more information from Perforce .

KDiff3

KDiff3 is a free diff tool which can also handle directories. You can download it from here .

ExamDiff

ExamDiff Standard is freeware. It can handle files but not directories. ExamDiff Pro is shareware and adds a number of goodies including directory diff and editing capability. In both flavours, version 3.2 and above can handle unicode. You can download them from PrestoSoft .

Beyond Compare

Similar to ExamDiff Pro, this is an excellent shareware diff tool which can handle directory diffs and unicode. Download it from Scooter Software .

Araxis Merge

Araxis Merge is a useful commercial tool for diff and merging both files and folders. It does three-way comparison in merges and has synchronization links to use if you've changed the order of functions. Download it from Araxis .

SciTE

This text editor includes syntax colouring for unified diffs, making them much easier to read. Download it from Scintilla .

Notepad2

Notepad2 is designed as a replacement for the standard Windows Notepad program, and is based on the Scintilla open-source edit control. As well as being good for viewing unified diffs, it is much better than the Windows notepad for most jobs. Download it for free here .

Read the section called “External Program Settings” for information on how to set up TortoiseSVN to use these tools.

Adding New Files And Directories

Figure 4.26. Explorer context menu for unversioned files

Explorer context menu for unversioned files


If you created new files and/or directories during your development process then you need to add them to source control too. Select the file(s) and/or directory and use TortoiseSVNAdd.

After you added the files/directories to source control the file appears with a added icon overlay which means you first have to commit your working copy to make those files/directories available to other developers. Adding a file/directory does not affect the repository!

Many Adds

You can also use the Add command on already versioned folders. In that case, the add dialog will show you all unversioned files inside that versioned folder. This helps if you have many new files and need to add them all at once.

To add files from outside your working copy you can use the drag-and-drop handler:

  1. select the files you want to add

  2. right-drag them to the new location inside the working copy

  3. release the right mouse button

  4. select Context MenuSVN Add files to this WC. The files will then be copied to the working copy and added to version control.

You can also add files within a working copy simply by left-dragging and dropping them onto the commit dialog.

If you add a file or folder by mistake, you can undo the addition before you commit using TortoiseSVNUndo add....

Copying/Moving/Renaming Files and Folders

It often happens that you already have the files you need in another project in your repository, and you simply want to copy them across. You could simply copy the files and add them as described above, but that would not give you any history. And if you subsequently fix a bug in the original files, you can only merge the fix automatically if the new copy is related to the original in Subversion.

The easiest way to copy files and folders from within a working copy is to use the right-drag menu. When you right-drag a file or folder from one working copy to another, or even within the same folder, a context menu appears when you release the mouse.

Figure 4.27. Right drag menu for a directory under version control

Right drag menu for a directory under version control


Now you can copy existing versioned content to a new location, possibly renaming it at the same time.

You can also copy or move versioned files within a working copy, or between two working copies, using the familiar cut-and-paste method. Use the standard Windows Copy or Cut to copy one or more versioned items to the clipboard. If the clipboard contains such versioned items, you can then use TortoiseSVNPaste (note: not the standard Windows Paste) to copy or move those items to the new working copy location.

You can copy files and folders from your working copy to another location in the repository using TortoiseSVNBranch/Tag. Refer to the section called “Creating a Branch or Tag” to find out more.

You can locate an older version of a file or folder in the log dialog and copy it to a new location in the repository directly from the log dialog using Context menuCreate branch/tag from revision. Refer to the section called “Getting Additional Information” to find out more.

You can also use the repository browser to locate content you want, and copy it into your working copy directly from the repository, or copy between two locations within the repository. Refer to the section called “The Repository Browser” to find out more.

Cannot copy between repositories

Whilst you can copy or move files and folders within a repository, you cannot copy or move from one repository to another while preserving history using TortoiseSVN. Not even if the repositories live on the same server. All you can do is copy the content in its current state and add it as new content to the second repository.

If you are uncertain whether two URLs on the same server refer to the same or different repositories, use the repo browser to open one URL and find out where the repository root is. If you can see both locations in one repo browser window then they are in the same repository.

Ignoring Files And Directories

Figure 4.28. Explorer context menu for unversioned files

Explorer context menu for unversioned files


In most projects you will have files and folders that should not be subject to version control. These might include files created by the compiler, *.obj, *.lst, maybe an output folder used to store the executable. Whenever you commit changes, TortoiseSVN shows your unversioned files, which fills up the file list in the commit dialog. Of course you can turn off this display, but then you might forget to add a new source file.

The best way to avoid these problems is to add the derived files to the project's ignore list. That way they will never show up in the commit dialog, but genuine unversioned source files will still be flagged up.

If you right click on a single unversioned file, and select the command TortoiseSVNAdd to Ignore List from the context menu, a submenu appears allowing you to select just that file, or all files with the same extension. If you select multiple files, there is no submenu and you can only add those specific files/folders.

If you want to remove one or more items from the ignore list, right click on those items and select TortoiseSVNRemove from Ignore List You can also access a folder's svn:ignore property directly. That allows you to specify more general patterns using filename globbing, described in the section below. Read the section called “Project Settings” for more information on setting properties directly. Please be aware that each ignore pattern has to be placed on a separate line. Separating them by spaces does not work.

The Global Ignore List

Another way to ignore files is to add them to the global ignore list. The big difference here is that the global ignore list is a client property. It applies to all Subversion projects, but on the client PC only. In general it is better to use the svn:ignore property where possible, because it can be applied to specific project areas, and it works for everyone who checks out the project. Read the section called “General Settings” for more information.

Ignoring Versioned Items

Versioned files and folders can never be ignored - that's a feature of Subversion. If you versioned a file by mistake, read the section called “Ignore files which are already versioned” for instructions on how to “unversion” it.

Pattern Matching in Ignore Lists

Subversion's ignore patterns make use of filename globbing, a technique originally used in Unix to specify files using meta-characters as wildcards. The following characters have special meaning:

*

Matches any string of characters, including the empty string (no characters).

?

Matches any single character.

[...]

Matches any one of the characters enclosed in the square brackets. Within the brackets, a pair of characters separated by “-” matches any character lexically between the two. For example [AGm-p] matches any one of A, G, m, n, o or p.

Pattern matching is case sensitive, which can cause problems on Windows. You can force case insensitivity the hard way by pairing characters, eg. to ignore *.tmp regardless of case, you could use a pattern like *.[Tt][Mm][Pp].

If you want an official definition for globbing, you can find it in the IEEE specifications for the shell command language Pattern Matching Notation .

No Paths in Global Ignore List

You should not include path information in your pattern. The pattern matching is intended to be used against plain file names and folder names. If you want to ignore all CVS folders, just add CVS to the ignore list. There is no need to specify CVS */CVS as you did in earlier versions. If you want to ignore all tmp folders when they exist within a prog folder but not within a doc folder you should use the svn:ignore property instead. There is no reliable way to achieve this using global ignore patterns.

Deleting, Moving and Renaming

Unlike CVS, Subversion allows renaming and moving of files and folders. So there are menu entries for delete and rename in the TortoiseSVN submenu.

Figure 4.29. Explorer context menu for versioned files

Explorer context menu for versioned files


Deleting files and folders

Use TortoiseSVNDelete to remove files or folders from subversion.

When you TortoiseSVNDelete a file, it is removed from your working copy immediately as well as being marked for deletion in the repository on next commit. The file's parent folder shows a “deleted” icon overlay. Up until you commit the change, you can get the file back using TortoiseSVNRevert on the parent folder.

When you TortoiseSVNDelete a folder, it remains in your working copy, but the overlay changes to indicate that it is marked for deletion. Up until you commit the change, you can get the folder back using TortoiseSVNRevert on the folder itself. This difference in behaviour between files and folders is a part of Subversion, not TortoiseSVN.

If you want to delete an item from the repository, but keep it locally as an unversioned file/folder, use Extended Context MenuDelete (keep local). You have to hold the Shift key while right clicking on the item in the explorer list pane (right pane) in order to see this in the extended context menu.

If a file is deleted via the explorer instead of using the TortoiseSVN context menu, the commit dialog shows those files and lets you remove them from version control too before the commit. However, if you update your working copy, Subversion will spot the missing file and replace it with the latest version from the repository. If you need to delete a version-controlled file, always use TortoiseSVNDelete so that Subversion doesn't have to guess what you really want to do.

If a folder is deleted via the explorer instead of using the TortoiseSVN context menu, your working copy will be broken and you will be unable to commit. If you update your working copy, Subversion will replace the missing folder with the latest version from the repository and you can then delete it the correct way using TortoiseSVNDelete.

Getting a deleted file or folder back

If you have deleted a file or a folder and already committed that delete operation to the repository, then a normal TortoiseSVNRevert can't bring it back anymore. But the file or folder is not lost at all. If you know the revision the file or folder got deleted (if you don't, use the log dialog to find out) open the repository browser and switch to that revision. Then select the file or folder you deleted, right-click and select Context MenuCopy to... as the target for that copy operation select the path to your working copy.

Moving files and folders

If you want to do a simple in-place rename of a file or folder, use Context MenuRename... Enter the new name for the item and you're done.

If you want to move files around inside your working copy, perhaps to a different sub-folder, use the right-mouse drag-and-drop handler:

  1. select the files or directories you want to move

  2. right-drag them to the new location inside the working copy

  3. release the right mouse button

  4. in the popup menu select Context MenuSVN Move versioned files here

Commit the parent folder

Since renames and moves are done as a delete followed by an add you must commit the parent folder of the renamed/moved file so that the deleted part of the rename/move will show up in the commit dialog. If you don't commit the removed part of the rename/move, it will stay behind in the repository and when your co-workers update, the old file will not be removed. i.e. they will have both the old and the new copies.

You must commit a folder rename before changing any of the files inside the folder, otherwise your working copy can get really messed up.

Another way of moving or copying files is to use the Windows copy/cut commands. Select the files you want to copy, right-click and choose Context MenuCopy from the explorer context menu. Then browse to the target folder, right-click and choose TortoiseSVNPaste. For moving files, choose Context MenuCut instead of Context MenuCopy.

You can also use the repository browser to move items around. Read the section called “The Repository Browser” to find out more.

Do Not SVN Move Externals

You should not use the TortoiseSVN Move or Rename commands on a folder which has been created using svn:externals. This action would cause the external item to be deleted from its parent repository, probably upsetting many other people. If you need to move an externals folder you should use an ordinary shell move, then adjust the svn:externals properties of the source and destination parent folders.

Changing case in a filename

Making case-only changes to a filename is tricky with Subversion on Windows, because for a short time during a rename, both filenames have to exist. As Windows has a case-insensitive file system, this does not work using the usual Rename command.

Fortunately there are (at least) two possible methods to rename a file without losing its log history. It is important to rename it within subversion. Just renaming in the explorer will corrupt your working copy!

Solution A) (recommended)

  1. Commit the changes in your working copy.

  2. Rename the file from UPPERcase to upperCASE directly in the repository using the repository browser.

  3. Update your working copy.

Solution B)

  1. Rename from UPPERcase to UPPERcase_ with the rename command in the TortoiseSVN submenu.

  2. Commit the changes.

  3. Rename from UPPERcase_ to upperCASE.

  4. Commit the changes.

Dealing with filename case conflicts

If the repository already contains two files with the same name but differing only in case (e.g. TEST.TXT and test.txt), you will not be able to update or checkout the parent directory on a Windows client. Whilst Subversion supports case-sensitive filenames, Windows does not.

This sometimes happens when two people commit, from separate working copies, files which happen to have the same name, but with a case difference. It can also happen when files are committed from a system with a case-sensitive file system, like Linux.

In that case, you have to decide which one of them you want to keep and delete (or rename) the other one from the repository.

Preventing two files with the same name

There is a server hook script available at: http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ that will prevent checkins which result in case conflicts.

Repairing File Renames

Sometimes your friendly IDE will rename files for you as part of a refactoring exercise, and of course it doesn't tell Subversion. If you try to commit your changes, Subversion will see the old filename as missing and the new one as an unversioned file. You could just check the new filename to get it added in, but you would then lose the history tracing, as Subversion does not know the files are related.

A better way is to notify Subversion that this change is actually a rename, and you can do this within the Commit and Check for Modifications dialogs. Simply select both the old name (missing) and the new name (unversioned) and use Context MenuRepair Move to pair the two files as a rename.

Deleting Unversioned Files

Usually you set your ignore list such that all generated files are ignored in Subversion. But what if you want to clear all those ignored items to produce a clean build? Usually you would set that in your makefile, but if you are debugging the makefile, or changing the build system it is useful to have a way of clearing the decks.

TortoiseSVN provides just such an option using Extended Context MenuDelete unversioned items.... You have to hold the Shift while right clicking on a folder in the explorer list pane (right pane) in order to see this in the extended context menu. This will produce a dialog which lists all unversioned files anywhere in your working copy. You can then select or deselect items to be removed.

When such items are deleted, the recycle bin is used, so if you make a mistake here and delete a file that should have been versioned, you can still recover it.

Undo Changes

If you want to undo all changes you made in a file since the last update you need to select the file, right click to pop up the context menu and then select the command TortoiseSVNRevert A dialog will pop up showing you the files that you've changed and can revert. Select those you want to revert and click on OK.

Figure 4.30. Revert dialog

Revert dialog


If you want to undo a deletion or a rename, you need to use Revert on the parent folder as the deleted item does not exist for you to right-click on.

If you want to undo the addition of an item, this appears in the context menu as TortoiseSVNUndo add.... This is really a revert as well, but the name has been changed to make it more obvious.

The columns in this dialog can be customized in the same way as the columns in the Check for modifications dialog. Read the section called “Local and Remote Status” for further details.

Since revert is sometimes used to clean up a working copy, there is an extra button which allows you to delete unversioned items as well. When you click this button another dialog comes up listing all the unversioned items, which you can then select for deletion.

Undoing Changes which have been Committed

Revert will only undo your local changes. It does not undo any changes which have already been committed. If you want to undo all the changes which were committed in a particular revision, read the section called “Revision Log Dialog” for further information.

Revert is Slow

When you revert changes you may find that the operation takes a lot longer than you expect. This is because the modified version of the file is sent to the recycle bin, so you can retrieve your changes if you reverted by mistake. However, if your recycle bin is full, Windows takes a long time to find a place to put the file. The solution is simple: either empty the recycle bin or deactivate the Use recycle bin when reverting box in TortoiseSVN's settings.

Cleanup

If a Subversion command cannot complete successfully, perhaps due to server problems, your working copy can be left in an inconsistent state. In that case you need to use TortoiseSVNCleanup on the folder. It is a good idea to do this at the top level of the working copy.

Cleanup has another useful side effect. If a file date changes but its content doesn't, Subversion cannot tell whether it has really changed except by doing a byte-by-byte comparison with the pristine copy. If you have a lot of files in this state it makes acquiring status very slow, which will make many dialogs slow to respond. Executing a Cleanup on your working copy will repair these “broken” timestamps and restore status checks to full speed.

Use Commit Timestamps

Some earlier releases of Subversion were affected by a bug which caused timestamp mismatch when you check out with the Use commit timestamps option checked. Use the Cleanup command to speed up these working copies.

Project Settings

Figure 4.31. Explorer property page, Subversion tab

Explorer property page, Subversion tab


Sometimes you want to have more detailed information about a file/directory than just the icon overlay. You can get all the information Subversion provides in the explorer properties dialog. Just select the file or directory and select Windows Menuproperties in the context menu (note: this is the normal properties menu entry the explorer provides, not the one in the TortoiseSVN submenu!). In the properties dialog box TortoiseSVN has added a new property page for files/folders under Subversion control, where you can see all relevant information about the selected file/directory.

Subversion Properties

Figure 4.32. Subversion property page

Subversion property page


You can read and set the Subversion properties from the Windows properties dialog, but also from TortoiseSVNproperties and within TortoiseSVN's status lists, from Context menuproperties.

You can add your own properties, or some properties with a special meaning in Subversion. These begin with svn:. svn:externals is such a property; see how to handle externals in the section called “External Items”.

svn:keywords

Subversion supports CVS-like keyword expansion which can be used to embed filename and revision information within the file itself. Keywords currently supported are:

$Date$

Date of last known commit. This is based on information obtained when you update your working copy. It does not check the repository to find more recent changes.

$Revision$

Revision of last known commit.

$Author$

Author who made the last known commit.

$HeadURL$

The full URL of this file in the repository.

$Id$

A compressed combination of the previous four keywords.

To find out how to use these keywords, look at the svn:keywords section in the Subversion book, which gives a full description of these keywords and how to enable and use them.

For more information about properties in Subversion see the Special Properties .

Adding and Editing Properties

Figure 4.33. Adding properties

Adding properties


To add a new property, first click on Add.... Select the required property name from the combo box, or type in a name of your own choice, then enter a value in the box below. Properties which take multiple values, such as an ignore list, can be entered on multiple lines. Click on OK to add that property to the list.

If you want to apply a property to many items at once, select the files/folders in explorer, then select Context menuproperties

If you want to apply the property to every file and folder in the hierarchy below the current folder, check the Recursive checkbox.

Some properties, for example svn:needs-lock, can only be applied to files, so the property name doesn't appear in the drop down list for folders. You can still apply such a property recursively to all files in a hierarchy, but you have to type in the property name yourself.

If you wish to edit an existing property, select that property from the list of existing properties, then click on Edit....

If you wish to remove an existing property, select that property from the list of existing properties, then click on Remove.

The svn:externals property can be used to pull in other projects from the same repository or a completely different repository. For more information, read the section called “External Items”.

Exporting and Importing Properties

Often you will find yourself applying the same set of properties many times, for example bugtraq:logregex. To simplify the process of copying properties from one project to another, you can use the Export/Import feature.

From the file or folder where the properties are already set, use TortoiseSVNproperties, select the properties you wish to export and click on Export.... You will be prompted for a filename where the property names and values will be saved.

From the folder(s) where you wish to apply these properties, use TortoiseSVNproperties and click on Import.... You will be prompted for a filename to import from, so navigate to the place you saved the export file previously and select it. The properties will be added to the folders non-recursively.

If you want to add properties to a tree recursively, follow the steps above, then in the property dialog select each property in turn, click on Edit..., check the Apply property recursively box and click on OK.

The Import file format is binary and proprietary to TortoiseSVN. Its only purpose is to transfer properties using Import and Export, so there is no need to edit these files.

Binary Properties

TortoiseSVN can handle binary property values using files. To read a binary property value, Save... to a file. To set a binary value, use a hex editor or other appropriate tool to create a file with the content you require, then Load... from that file.

Although binary properties are not often used, they can be useful in some applications. For example if you are storing huge graphics files, or if the application used to load the file is huge, you might want to store a thumbnail as a property so you can obtain a preview quickly.

Automatic property setting

You can configure Subversion and TortoiseSVN to set properties automatically on files and folders when they are added to the repository. There are two ways of doing this.

You can edit the subversion configuration file to enable this feature on your client. The General page of TortoiseSVN's settings dialog has an edit button to take you there directly. The config file is a simple text file which controls some of subversion's workings. You need to change two things: firstly in the section headed miscellany uncomment the line enable-auto-props = yes. Secondly you need to edit the section below to define which properties you want added to which file types. This method is a standard subversion feature and works with any subversion client. However it has to be defined on each client individually - there is no way to propagate these settings from the repository.

An alternative method is to set the tsvn:autoprops property on folders, as described in the next section. This method only works for TortoiseSVN clients, but it does get propagated to all working copies on update.

Whichever method you choose, you should note that auto-props are only applied to files at the time they are added to the repository. Auto-props will never change the properties of files which are already versioned.

If you want to be absolutely sure that new files have the correct properties applied, you should set up a repository pre-commit hook to reject commits where the required properties are not set.

Commit properties

Subversion properties are versioned. After you change or add a property you have to commit your changes.

Conflicts on properties

If there's a conflict on committing the changes, because another user has changed the same property, Subversion generates a .prej file. Delete this file after you have resolved the conflict.

TortoiseSVN Project Properties

TortoiseSVN has a few special properties of its own, and these begin with tsvn:.

  • tsvn:logminsize sets the minimum length of a log message for a commit. If you enter a shorter message than specified here, the commit is disabled. This feature is very useful for reminding you to supply a proper descriptive message for every commit. If this property is not set, or the value is zero, empty log messages are allowed.

    tsvn:lockmsgminsize sets the minimum length of a lock message. If you enter a shorter message than specified here, the lock is disabled. This feature is very useful for reminding you to supply a proper descriptive message for every lock you get. If this property is not set, or the value is zero, empty lock messages are allowed.

  • tsvn:logwidthmarker is used with projects which require log messages to be formatted with some maximum width (typically 80 characters) before a line break. Setting this property to a non-zero will do 2 things in the log message entry dialog: it places a marker to indicate the maximum width, and it disables word wrap in the display, so that you can see whether the text you entered is too long. Note: this feature will only work correctly if you have a fixed-width font selected for log messages.

  • tsvn:logtemplate is used with projects which have rules about log message formatting. The property holds a multi-line text string which will be inserted in the commit message box when you start a commit. You can then edit it to include the required information. Note: if you are also using tsvn:logminsize, be sure to set the length longer than the template or you will lose the protection mechanism.

  • Subversion allows you to set “autoprops” which will be applied to newly added or imported files, based on the file extension. This depends on every client having set appropriate autoprops in their subversion configuration file. tsvn:autoprops can be set on folders and these will be merged with the user's local autoprops when importing or adding files. The format is the same as for subversion autoprops, e.g. *.sh = svn:eol-style=native;svn:executable sets two properties on files with the .sh extension.

    If there is a conflict between the local autoprops and tsvn:autoprops, the project settings take precedence because they are specific to that project.

  • In the Commit dialog you have the option to paste in the list of changed files, including the status of each file (added, modified, etc). tsvn:logfilelistenglish defines whether the file status is inserted in English or in the localized language. If the property is not set, the default is true.

  • TortoiseSVN can use spell checker modules which are also used by OpenOffice and Mozilla. If you have those installed this property will determine which spell checker to use, i.e. in which language the log messages for your project should be written. tsvn:projectlanguage sets the language module the spell checking engine should use when you enter a log message. You can find the values for your language on this page: MSDN: Language Identifiers .

    You can enter this value in decimal, or in hexadecimal if prefixed with 0x. For example English (US) can be entered as 0x0409 or 1033.

  • The property tsvn:logsummary is used to extract a portion of the log message which is then shown in the log dialog as the log message summary.

    The value of the tsvn:logsummary property must be set to a one line regex string which contains one regex group. Whatever matches that group is used as the summary.

    An example: \[SUMMARY\]:\s+(.*) Will catch everything after “[SUMMARY]” in the log message and use that as the summary.

  • The property tsvn:logrevregex defines a regular expression which matches references to revisions in a log message. This is used in the log dialog to turn such references into links which when clicked will either scroll to that revision (if the revision is already shown in the log dialog, or if it's available from the log cache) or open a new log dialog showing that revision.

    The regular expression must match the whole reference, not just the revision number. The revision number is extracted from the matched reference string automatically.

    If this property is not set, a default regular expression is used to link revision references.

  • When you want to add a new property, you can either pick one from the list in the combo box, or you can enter any property name you like. If your project uses some custom properties, and you want those properties to appear in the list in the combo box (to avoid typos when you enter a property name), you can create a list of your custom properties using tsvn:userfileproperties and tsvn:userdirproperties. Apply these properties to a folder. When you go to edit the properties of any child item, your custom properties will appear in the list of pre-defined property names.

Some tsvn: properties require a true/false value. TortoiseSVN also understands yes as a synonym for true and no as a synonym for false.

TortoiseSVN can integrate with some bug tracking tools. This uses project properties that start with bugtraq:. Read the section called “Integration with Bug Tracking Systems / Issue Trackers” for further information.

It can also integrate with some web-based repository browsers, using project properties that start with webviewer:. Read the section called “Integration with Web-based Repository Viewers” for further information.

Set the project properties on folders

These special project properties must be set on folders for the system to work. When you commit a file or folder the properties are read from that folder. If the properties are not found there, TortoiseSVN will search upwards through the folder tree to find them until it comes to an unversioned folder, or the tree root (eg. C:\) is found. If you can be sure that each user checks out only from e.g trunk/ and not some sub-folder, then it is sufficient to set the properties on trunk/. If you can't be sure, you should set the properties recursively on each sub-folder. A property setting deeper in the project hierarchy overrides settings on higher levels (closer to trunk/).

For project properties only, i.e. tsvn:, bugtraq: and webviewer: you can use the Recursive checkbox to set the property to all sub-folders in the hierarchy, without also setting it on all files.

When you add new sub-folders to a working copy using TortoiseSVN, any project properties present in the parent folder will automatically be added to the new child folder too.

Limitations Using the Repository Browser

Fetching properties remotely is a slow operation, so some of the features described above will not work in the repository browser as they do in a working copy.

  • When you add a property using the repo browser, only the standard svn: properties are offered in the pre-defined list. Any other property name must be entered manually.

  • Properties cannot be set or deleted recursively using the repo browser.

  • Project properties will not be propagated automatically when a child folder is added using the repo browser.

  • tsvn:autoprops will not set properties on files which are added using the repo browser.

Caution

Although TortoiseSVN's project properties are extremely useful, they only work with TortoiseSVN, and some will only work in newer versions of TortoiseSVN. If people working on your project use a variety of Subversion clients, or possibly have old versions of TortoiseSVN, you may want to use repository hooks to enforce project policies. project properties can only help to implement a policy, they cannot enforce it.

External Items

Sometimes it is useful to construct a working copy that is made out of a number of different checkouts. For example, you may want different files or subdirectories to come from different locations in a repository, or perhaps from different repositories altogether. If you want every user to have the same layout, you can define the svn:externals properties to pull in the specified resource at the locations where they are needed.

External Folders

Let's say you check out a working copy of /project1 to D:\dev\project1. Select the folder D:\dev\project1, right click and choose Windows MenuProperties from the context menu. The Properties Dialog comes up. Then go to the Subversion tab. There, you can set properties. Click Add.... Select the svn:externals property from the combobox and write in the edit box the repository URL in the format url folder or if you want to specify a particular revision, -rREV url folder You can add multiple external projects, 1 per line. Suppose that you have set these properties on D:\dev\project1:

http://sounds.red-bean.com/repos  sounds
http://graphics.red-bean.com/repos/fast%20graphics  "quick graphs"
-r21 http://svn.red-bean.com/repos/skin-maker  skins/toolkit

Now click Set and commit your changes. When you (or any other user) update your working copy, Subversion will create a sub-folder D:\dev\project1\sounds and checkout the sounds project, another sub-folder D:\dev\project1\quick_graphs containing the graphics project, and finally a nested sub-folder D:\dev\project1\skins\toolkit containing revision 21 of the skin-maker project.

URLs must be properly escaped or they will not work, e.g. you must replace each space with %20 as shown in the second example above.

If you want the local path to include spaces or other special characters, you can enclose it in double quotes, or you can use the \ (backslash) character as a Unix shell style escape character preceding any special character. Of course this also means that you must use / (forward slash) as a path delimiter. Note that this behaviour is new in Subversion 1.6 and will not work with older clients.

Use explicit revision numbers

You should strongly consider using explicit revision numbers in all of your externals definitions, as described above. Doing so means that you get to decide when to pull down a different snapshot of external information, and exactly which snapshot to pull. Besides the common sense aspect of not being surprised by changes to third-party repositories that you might not have any control over, using explicit revision numbers also means that as you backdate your working copy to a previous revision, your externals definitions will also revert to the way they looked in that previous revision, which in turn means that the external working copies will be updated to match they way they looked back when your repository was at that previous revision. For software projects, this could be the difference between a successful and a failed build of an older snapshot of your complex code base.

Older svn:externals definitions

The format shown here was introduced in Subversion 1.5. You may also see the older format which has the same information in a different order. The new format is preferred as it supports several useful features described below, but it will not work on older clients. The differences are shown in the Subversion Book .

If the external project is in the same repository, any changes you make there will be included in the commit list when you commit your main project.

If the external project is in a different repository, any changes you make to the external project will be notified when you commit the main project, but you have to commit those external changes separately.

If you use absolute URLs in svn:externals definitions and you have to relocate your working copy (i.e., if the URL of your repository changes), then your externals won't change and might not work anymore.

To avoid such problems, Subversion clients version 1.5 and higher support relative external URLs. Four different methods of specifying a relative URL are supported. In the following examples, assume we have two repositories: one at http://example.com/svn/repos-1 and another at http://example.com/svn/repos-2. We have a checkout of http://example.com/svn/repos-1/project/trunk into C:\Working and the svn:externals property is set on trunk.

Relative to parent directory

These URLs always begin with the string ../ for example:

../../widgets/foo  common/foo-widget

This will extract http://example.com/svn/repos-1/widgets/foo into C:\Working\common\foo-widget.

Note that the URL is relative to the URL of the directory with the svn:externals property, not to the directory where the external is written to disk.

Relative to repository root

These URLs always begin with the string ^/ for example:

^/widgets/foo  common/foo-widget

This will extract http://example.com/svn/repos-1/widgets/foo into C:\Working\common\foo-widget.

You can easily refer to other repositories with the same SVNParentPath (a common directory holding several repositories). For example:

^/../repos-2/hammers/claw  common/claw-hammer

This will extract http://example.com/svn/repos-2/hammers/claw into C:\Working\common\claw-hammer.

Relative to scheme

URLs beginning with the string // copy only the scheme part of the URL. This is useful when the same hostname must the accessed with different schemes depending upon network location; e.g. clients in the intranet use http:// while external clients use svn+ssh://. For example:

//example.com/svn/repos-1/widgets/foo  common/foo-widget

This will extract http://example.com/svn/repos-1/widgets/foo or svn+ssh://example.com/svn/repos-1/widgets/foo depending on which method was used to checkout C:\Working.

Relative to the server's hostname

URLs beginning with the string / copy the scheme and the hostname part of the URL, for example:

/svn/repos-1/widgets/foo  common/foo-widget

This will extract http://example.com/svn/repos-1/widgets/foo into C:\Working\common\foo-widget. But if you checkout your working copy from another server at svn+ssh://another.mirror.net/svn/repos-1/project1/trunk then the external reference will extract svn+ssh://another.mirror.net/svn/repos-1/widgets/foo.

You can also specify a peg revision after the URL if required, e.g. http://sounds.red-bean.com/repos@19.

If you need more information how TortoiseSVN handles Properties read the section called “Project Settings”.

To find out about different methods of accessing common sub-projects read the section called “Include a common sub-project”.

External Files

As of Subversion 1.6 you can add single file externals to your working copy using the same syntax as for folders. However, there are some restrictions.

  • The path to the file external must place the file in an existing versioned folder. In general it makes most sense to place the file directly in the folder that has svn:externals set, but it can be in a versioned sub-folder if necessary. By contrast, directory externals will automatically create any intermediate unversioned folders as required.

  • The URL for a file external must be in the same repository as the URL that the file external will be inserted into; inter-repository file externals are not supported.

A file external behaves just like any other versioned file in many respects, but they cannot be moved or deleted using the normal commands; the svn:externals property must be modified instead.

File externals support incomplete in Subversion 1.6

In subversion 1.6 it is not possible to remove a file external from your working copy once you have added it, even if you delete the svn:externals property altogether. You have to checkout a fresh working copy to remove the file.

Branching / Tagging

One of the features of version control systems is the ability to isolate changes onto a separate line of development. This line is known as a branch. Branches are often used to try out new features without disturbing the main line of development with compiler errors and bugs. As soon as the new feature is stable enough then the development branch is merged back into the main branch (trunk).

Another feature of version control systems is the ability to mark particular revisions (e.g. a release version), so you can at any time recreate a certain build or environment. This process is known as tagging.

Subversion does not have special commands for branching or tagging, but uses so-called “cheap copies” instead. Cheap copies are similar to hard links in Unix, which means that instead of making a complete copy in the repository, an internal link is created, pointing to a specific tree/revision. As a result branches and tags are very quick to create, and take up almost no extra space in the repository.

Creating a Branch or Tag

If you have imported your project with the recommended directory structure, creating a branch or tag version is very simple:

Figure 4.34. The Branch/Tag Dialog

The Branch/Tag Dialog


Select the folder in your working copy which you want to copy to a branch or tag, then select the command TortoiseSVNBranch/Tag....

The default destination URL for the new branch will be the source URL on which your working copy is based. You will need to edit that URL to the new path for your branch/tag. So instead of

    http://svn.collab.net/repos/ProjectName/trunk

you might now use something like

    http://svn.collab.net/repos/ProjectName/tags/Release_1.10

If you can't remember the naming convention you used last time, click the button on the right to open the repository browser so you can view the existing repository structure.

Now you have to select the source of the copy. Here you have three options:

HEAD revision in the repository

The new branch is copied directly in the repository from the HEAD revision. No data needs to be transferred from your working copy, and the branch is created very quickly.

Specific revision in the repository

The new branch is copied directly in the repository but you can choose an older revision. This is useful if you forgot to make a tag when you released your project last week. If you can't remember the revision number, click the button on the right to show the revision log, and select the revision number from there. Again no data is transferred from your working copy, and the branch is created very quickly.

Working copy

The new branch is an identical copy of your local working copy. If you have updated some files to an older revision in your WC, or if you have made local changes, that is exactly what goes into the copy. Naturally this sort of complex tag may involve transferring data from your WC back to the repository if it does not exist there already.

If you want your working copy to be switched to the newly created branch automatically, use the Switch working copy to new branch/tag checkbox. But if you do that, first make sure that your working copy does not contain modifications. If it does, those changes will be merged into the branch WC when you switch.

Press OK to commit the new copy to the repository. Don't forget to supply a log message. Note that the copy is created inside the repository.

Note that unless you opted to switch your working copy to the newly created branch, creating a Branch or Tag does not affect your working copy. Even if you create the branch from your WC, those changes are committed to the new branch, not to the trunk, so your WC may still be marked as modified with respect to the trunk.

Other ways to create a branch or tag

You can also create a branch or tag without having a working copy. To do that, open the repository browser. You can there drag folders to a new location. You have to hold down the Ctrl key while you drag to create a copy, otherwise the folder gets moved, not copied.

You can also drag a folder with the right mouse button. Once you release the mouse button you can choose from the context menu whether you want the folder to be moved or copied. Of course to create a branch or tag you must copy the folder, not move it.

Yet another way is from the log dialog. You can show the log dialog for e.g. trunk, select a revision (either the HEAD revision at the very top or an earlier revision), right-click and choose create branch/tag from revision...

To Checkout or to Switch...

...that is (not really) the question. While a checkout downloads everything from the desired branch in the repository to your working directory, TortoiseSVNSwitch... only transfers the changed data to your working copy. Good for the network load, good for your patience. :-)

To be able to work with your freshly generated branch or tag you have several ways to handle it. You can:

  • TortoiseSVNCheckout to make a fresh checkout in an empty folder. You can check out to any location on your local disk and you can create as many working copies from your repository as you like.

  • Switch your current working copy to the newly created copy in the repository. Again select the top level folder of your project and use TortoiseSVNSwitch... from the context menu.

    In the next dialog enter the URL of the branch you just created. Select the Head Revision radio button and click on OK. Your working copy is switched to the new branch/tag.

    Switch works just like Update in that it never discards your local changes. Any changes you have made to your working copy which have not yet been committed will be merged when you do the Switch. If you do not want this to happen then you must either commit the changes before switching, or revert your working copy to an already-committed revision (typically HEAD).

  • If you want to work on trunk and branch, but don't want the expense of a fresh checkout, you can use Windows Explorer to make a copy of your trunk checkout in another folder, then TortoiseSVNSwitch... that copy to your new branch.

Figure 4.35. The Switch Dialog

The Switch Dialog


Although Subversion itself makes no distinction between tags and branches, the way they are typically used differs a bit.

  • Tags are typically used to create a static snapshot of the project at a particular stage. As such they are not normally used for development - that's what branches are for, which is the reason we recommended the /trunk /branches /tags repository structure in the first place. Working on a tag revision is not a good idea, but because your local files are not write protected there is nothing to stop you doing this by mistake. However, if you try to commit to a path in the repository which contains /tags/, TortoiseSVN will warn you.

  • It may be that you need to make further changes to a release which you have already tagged. The correct way to handle this is to create a new branch from the tag first and commit the branch. Do your Changes on this branch and then create a new tag from this new branch, e.g. Version_1.0.1.

  • If you modify a working copy created from a branch and commit, then all changes go to the new branch and not the trunk. Only the modifications are stored. The rest remains a cheap copy.

Merging

Where branches are used to maintain separate lines of development, at some stage you will want to merge the changes made on one branch back into the trunk, or vice versa.

It is important to understand how branching and merging works in Subversion before you start using it, as it can become quite complex. It is highly recommended that you read the chapter Branching and Merging in the Subversion book, which gives a full description and many examples of how it is used.

The next point to note is that merging always takes place within a working copy. If you want to merge changes into a branch, you have to have a working copy for that branch checked out, and invoke the merge wizard from that working copy using TortoiseSVNMerge....

In general it is a good idea to perform a merge into an unmodified working copy. If you have made other changes in your WC, commit those first. If the merge does not go as you expect, you may want to revert the changes, and the Revert command will discard all changes including any you made before the merge.

There are three common use cases for merging which are handled in slightly different ways, as described below. The first page of the merge wizard asks you to select the method you need.

Merge a range of revisions

This method covers the case when you have made one or more revisions to a branch (or to the trunk) and you want to port those changes across to a different branch.

What you are asking Subversion to do is this: “Calculate the changes necessary to get [FROM] revision 1 of branch A [TO] revision 7 of branch A, and apply those changes to my working copy (of trunk or branch B).

Reintegrate a branch

This method covers the case when you have made a feature branch as discussed in the Subversion book. All trunk changes have been ported to the feature branch, week by week, and now the feature is complete you want to merge it back into the trunk. Because you have kept the feature branch synchronized with the trunk, the latest versions of branch and trunk will be absolutely identical except for your branch changes.

This is a special case of the tree merge described below, and it requires only the URL to merge from (normally) your development branch. It uses the merge-tracking features of Subversion to calculate the correct revision ranges to use, and perform additional checks which ensure that the branch has been fully updated with trunk changes. This ensures that you don't accidentally undo work that others have committed to trunk since you last synchronized changes.

After the merge, all branch development has been completely merged back into the main development line. The branch is now redundant and can be deleted.

Once you have performed a reintegrate merge you should not continue to use it for development. The reason for this is that if you try to resynchronize your existing branch from trunk later on, merge tracking will see your reintegration as a trunk change that has not yet been merged into the branch, and will try to merge the branch-to-trunk merge back into the branch! The solution to this is simply to create a new branch from trunk to continue the next phase of your development.

Merge two different trees

This is a more general case of the reintegrate method. What you are asking Subversion to do is: “Calculate the changes necessary to get [FROM] the head revision of the trunk [TO] the head revision of the branch, and apply those changes to my working copy (of the trunk).” The net result is that trunk now looks exactly like the branch.

If your server/repository does not support merge-tracking then this is the only way to merge a branch back to trunk. Another use case occurs when you are using vendor branches and you need to merge the changes following a new vendor drop into your trunk code. For more information read the chapter on vendor branches in the Subversion Book.

Merging a Range of Revisions

Figure 4.36. The Merge Wizard - Select Revision Range

The Merge Wizard - Select Revision Range


In the From: field enter the full folder URL of the branch or tag containing the changes you want to port into your working copy. You may also click ... to browse the repository and find the desired branch. If you have merged from this branch before, then just use the drop down list which shows a history of previously used URLs.

In the Revision range to merge field enter the list of revisions you want to merge. This can be a single revision, a list of specific revisions separated by commas, or a range of revisions separated by a dash, or any combination of these.

Important

There is an important difference in the way a revision range is specified with TortoiseSVN compared to the command line client. The easiest way to visualise it is to think of a fence with posts and fence panels.

With the command line client you specify the changes to merge using two “fence post” revisions which specify the before and after points.

With TortoiseSVN you specify the changeset to merge using “fence panels”. The reason for this becomes clear when you use the log dialog to specify revisions to merge, where each revision appears as a changeset.

If you are merging revisions in chunks, the method shown in the subversion book will have you merge 100-200 this time and 200-300 next time. With TortoiseSVN you would merge 100-200 this time and 201-300 next time.

This difference has generated a lot of heat on the mailing lists. We acknowledge that there is a difference from the command line client, but we believe that for the majority of GUI users it is easier to understand the method we have implemented.

The easiest way to select the range of revisions you need is to click on Show Log, as this will list recent changes with their log comments. If you want to merge the changes from a single revision, just select that revision. If you want to merge changes from several revisions, then select that range (using the usual Shift-modifier). Click on OK and the list of revision numbers to merge will be filled in for you.

If you want to merge changes back out of your working copy, to revert a change which has already been committed, select the revisions to revert and make sure the Reverse merge box is checked.

If you have already merged some changes from this branch, hopefully you will have made a note of the last revision merged in the log message when you committed the change. In that case, you can use Show Log for the Working Copy to trace that log message. Remembering that we are thinking of revisions as changesets, you should Use the revision after the end point of the last merge as the start point for this merge. For example, if you have merged revisions 37 to 39 last time, then the start point for this merge should be revision 40.

If you are using the merge tracking features of Subversion, you do not need to remember which revisions have already been merged - Subversion will record that for you. If you leave the revision range blank, all revisions which have not yet been merged will be included. Read the section called “Merge Tracking” to find out more.

If other people may be committing changes then be careful about using the HEAD revision. It may not refer to the revision you think it does if someone else made a commit after your last update.

Click Next and go to the section called “Merge Options”

Reintegrate a branch

Figure 4.37. The Merge Wizard - Reintegrate Merge

The Merge Wizard - Reintegrate Merge


To merge a feature branch back into the trunk you must start the merge wizard from within a working copy of the trunk.

In the From URL: field enter the full folder URL of the branch that you want to merge back. You may also click ... to browse the repository.

There are some conditions which apply to a reintegrate merge. Firstly, the server must support merge tracking. The working copy must be of depth infinite (no sparse checkouts), and it must not have any local modifications, switched items or items that have been updated to revisions other than HEAD. All changes to trunk made during branch development must have been merged across to the branch (or marked as having been merged). The range of revisions to merge will be calculated automatically.

Merging Two Different Trees

Figure 4.38. The Merge Wizard - Tree Merge

The Merge Wizard - Tree Merge


If you are using this method to merge a feature branch back to trunk, you need to start the merge wizard from within a working copy of trunk.

In the From: field enter the full folder URL of the trunk. This may sound wrong, but remember that the trunk is the start point to which you want to add the branch changes. You may also click ... to browse the repository.

In the To: field enter the full folder URL of the feature branch.

In both the From Revision field and the To Revision field, enter the last revision number at which the two trees were synchronized. If you are sure no-one else is making commits you can use the HEAD revision in both cases. If there is a chance that someone else may have made a commit since that synchronization, use the specific revision number to avoid losing more recent commits.

You can also use Show Log to select the revision.

Merge Options

This page of the wizard lets you specify advanced options, before starting the merge process. Most of the time you can just use the default settings.

You can specify the depth to use for the merge, i.e. how far down into your working copy the merge should go. The depth terms used are described in the section called “Checkout Depth”. The default depth is Working copy, which uses the existing depth setting, and is almost always what you want.

Most of the time you want merge to take account of the file's history, so that changes relative to a common ancestor are merged. Sometimes you may need to merge files which are perhaps related, but not in your repository. For example you may have imported versions 1 and 2 of a third party library into two separate directories. Although they are logically related, Subversion has no knowledge of this because it only sees the tarballs you imported. If you attempt to merge the difference between these two trees you would see a complete removal followed by a complete add. To make Subversion use only path-based differences rather than history-based differences, check the Ignore ancestry box. Read more about this topic in the Subversion book, Noticing or Ignoring Ancestry

You can specify the way that line ending and whitespace changes are handled. These options are described in the section called “Line-end and Whitespace Options”. The default behaviour is to treat all whitespace and line-end differences as real changes to be merged.

The checkbox marked Force the merge is used to avoid a tree conflict where an incoming delete affects a file that is either modified locally or not versioned at all. If the file is deleted then there is no way to recover it, which is why that option is not checked by default.

If you are using merge tracking and you want to mark a revision as having been merged, without actually doing the merge here, check the Only record the merge checkbox. There are two possible reasons you might want to do this. It may be that the merge is too complicated for the merge algorithms, so you code the changes by hand, then mark the change as merged so that the merge tracking algorithm is aware of it. Or you might want to prevent a particular revision from being merged. Marking it as already merged will prevent the merge occurring with merge-tracking-aware clients.

Now everything is set up, all you have to do is click on the Merge button. If you want to preview the results Test Merge simulates the merge operation, but does not modify the working copy at all. It shows you a list of the files that will be changed by a real merge, and notes files where conflicts may occur. Because merge tracking makes the merge process a lot more complicated, there is no guaranteed way to find out in advance whether the merge will complete without conflicts, so files marked as conflicted in a test merge may in fact merge without any problem.

The merge progress dialog shows each stage of the merge, with the revision ranges involved. This may indicate one more revision than you were expecting. For example if you asked to merge revision 123 the progress dialog will report “Merging revisions 122 through 123”. To understand this you need to remember that Merge is closely related to Diff. The merge process works by generating a list of differences between two points in the repository, and applying those differences to your working copy. The progress dialog is simply showing the start and end points for the diff.

Reviewing the Merge Results

The merge is now complete. It's a good idea to have a look at the merge and see if it's as expected. Merging is usually quite complicated. Conflicts often arise if the branch has drifted far from the trunk.

For Subversion clients and servers prior to 1.5, no merge information is stored and merged revisions have to be tracked manually. When you have tested the changes and come to commit this revision, your commit log message should always include the revision numbers which have been ported in the merge. If you want to apply another merge at a later time you will need to know what you have already merged, as you do not want to port a change more than once. For more information about this, refer to Best Practices for Merging in the Subversion book.

If your server and all clients are running Subversion 1.5 or higher, the merge tracking facility will record the revisions merged and avoid a revision being merged more than once. This makes your life much simpler as you can simply merge the entire revision range each time and know that only new revisions will actually be merged.

Branch management is important. If you want to keep this branch up to date with the trunk, you should be sure to merge often so that the branch and trunk do not drift too far apart. Of course, you should still avoid repeated merging of changes, as explained above.

Tip

If you have just merged a feature branch back into the trunk, the trunk now contains all the new feature code, and the branch is obsolete. You can now delete it from the repository if required.

Important

Subversion can't merge a file with a folder and vice versa - only folders to folders and files to files. If you click on a file and open up the merge dialog, then you have to give a path to a file in that dialog. If you select a folder and bring up the dialog, then you must specify a folder URL for the merge.

Merge Tracking

Subversion 1.5 introduced facilities for merge tracking. When you merge changes from one tree into another, the revision numbers merged are stored and this information can be used for several different purposes.

  • You can avoid the danger of merging the same revision twice (repeated merge problem). Once a revision is marked as having been merged, future merges which include that revision in the range will skip over it.

  • When you merge a branch back into trunk, the log dialog can show you the branch commits as part of the trunk log, giving better traceability of changes.

  • When you show the log dialog from within the merge dialog, revisions already merged are shown in grey.

  • When showing blame information for a file, you can choose to show the original author of merged revisions, rather than the person who did the merge.

  • You can mark revisions as do not merge by including them in the list of merged revisions without actually doing the merge.

Merge tracking information is stored in the svn:mergeinfo property by the client when it performs a merge. When the merge is committed the server stores that information in a database, and when you request merge, log or blame information, the server can respond appropriately. For the system to work properly you must ensure that the server, the repository and all clients are upgraded. Earlier clients will not store the svn:mergeinfo property and earlier servers will not provide the information requested by new clients.

Find out more about merge tracking from Subversion's Merge tracking documentation .

Handling Conflicts during Merge

Merging does not always go smoothly. Sometimes there is a conflict, and if you are merging multiple ranges, you generally want to resolve the conflict before merging of the next range starts. TortoiseSVN helps you through this process by showing the merge conflict callback dialog.

Figure 4.39. The Merge Conflict Callback Dialog

The Merge Conflict Callback Dialog


When a conflict occurs during the merge, you have three ways to handle it.

  1. You may decide that your local changes are much more important, so you want to discard the version from the repository and keep your local version. Or you might discard your local changes in favour of the repository version. This only relates to conflicting changes. Changes that can be merged are still merged. Only for the conflicting part your choice is used.

  2. Normally you will want to look at the conflicts and resolve them. In that case, choose the Edit Conflict which will start up your merge tool. When you are satisfied with the result, click Resolved.

  3. The last option is to postpone resolution and continue with merging. You can choose to do that for the current conflicted file, or for all files in the rest of the merge. However, if there are further changes in that file, it will not be possible to complete the merge.

If you do not want to use this interactive callback, there is a checkbox in the merge progress dialog Merge non-interactive. If this is set for a merge and the merge would result in a conflict, the file is marked as in conflict and the merge goes on. You will have to resolve the conflicts after the whole merge is finished. If it is not set, then before a file is marked as conflicted you get the chance to resolve the conflict during the merge. This has the advantage that if a file gets multiple merges (multiple revisions apply a change to that file), subsequent merges might succeed depending on which lines are affected. But of course you can't walk away to get a coffee while the merge is running ;)

Merge a Completed Branch

If you want to merge all changes from a feature branch back to trunk, then you can use the TortoiseSVNMerge reintegrate... from the extended context menu (hold down the Shift key while you right click on the file).

Figure 4.40. The Merge reintegrate Dialog

The Merge reintegrate Dialog


This dialog is very easy. All you have to do is set the options for the merge, as described in the section called “Merge Options”. The rest is done by TortoiseSVN automatically using merge tracking.

Feature Branch Maintenance

When you develop a new feature on a separate branch it is a good idea to work out a policy for re-integration when the feature is complete. If other work is going on in trunk at the same time you may find that the differences become significant over time, and merging back becomes a nightmare.

If the feature is relatively simple and development will not take long then you can adopt a simple approach, which is to keep the branch entirely separate until the feature is complete, then merge the branch changes back into trunk. In the merge wizard this would be a simple Merge a range of revisions, with the revision range being the revision span of the branch.

If the feature is going to take longer and you need to account for changes in trunk, then you need to keep the branch synchronised. This simply means that periodically you merge trunk changes into the branch, so that the branch contains all the trunk changes plus the new feature. The synchronisation process uses Merge a range of revisions. When the feature is complete then you can merge it back to trunk using either Reintegrate a branch or Merge two different trees.

Locking

Subversion generally works best without locking, using the “Copy-Modify-Merge” methods described earlier in the section called “The Copy-Modify-Merge Solution”. However there are a few instances when you may need to implement some form of locking policy.

  • You are using “unmergeable” files, for example, graphics files. If two people change the same file, merging is not possible, so one of you will lose their changes.

  • Your company has always used a locking revision control system in the past and there has been a management decision that “locking is best”.

Firstly you need to ensure that your Subversion server is upgraded to at least version 1.2. Earlier versions do not support locking at all. If you are using file:// access, then of course only your client needs to be updated.

How Locking Works in Subversion

By default, nothing is locked and anyone who has commit access can commit changes to any file at any time. Others will update their working copies periodically and changes in the repository will be merged with local changes.

If you Get a Lock on a file, then only you can commit that file. Commits by all other users will be blocked until you release the lock. A locked file cannot be modified in any way in the repository, so it cannot be deleted or renamed either, except by the lock owner.

However, other users will not necessarily know that you have taken out a lock. Unless they check the lock status regularly, the first they will know about it is when their commit fails, which in most cases is not very useful. To make it easier to manage locks, there is a new Subversion property svn:needs-lock. When this property is set (to any value) on a file, whenever the file is checked out or updated, the local copy is made read-only unless that working copy holds a lock for the file. This acts as a warning that you should not edit that file unless you have first acquired a lock. Files which are versioned and read-only are marked with a special overlay in TortoiseSVN to indicate that you need to acquire a lock before editing.

Locks are recorded by working copy location as well as by owner. If you have several working copies (at home, at work) then you can only hold a lock in one of those working copies.

If one of your co-workers acquires a lock and then goes on holiday without releasing it, what do you do? Subversion provides a means to force locks. Releasing a lock held by someone else is referred to as Breaking the lock, and forcibly acquiring a lock which someone else already holds is referred to as Stealing the lock. Naturally these are not things you should do lightly if you want to remain friends with your co-workers.

Locks are recorded in the repository, and a lock token is created in your local working copy. If there is a discrepancy, for example if someone else has broken the lock, the local lock token becomes invalid. The repository is always the definitive reference.

Getting a Lock

Select the file(s) in your working copy for which you want to acquire a lock, then select the command TortoiseSVNGet Lock....

Figure 4.41. The Locking Dialog

The Locking Dialog


A dialog appears, allowing you to enter a comment, so others can see why you have locked the file. The comment is optional and currently only used with Svnserve based repositories. If (and only if) you need to steal the lock from someone else, check the Steal lock box, then click on OK.

If you select a folder and then use TortoiseSVNGet Lock... the lock dialog will open with every file in every sub-folder selected for locking. If you really want to lock an entire hierarchy, that is the way to do it, but you could become very unpopular with your co-workers if you lock them out of the whole project. Use with care ...

Releasing a Lock

To make sure you don't forget to release a lock you don't need any more, locked files are shown in the commit dialog and selected by default. If you continue with the commit, locks you hold on the selected files are removed, even if the files haven't been modified. If you don't want to release a lock on certain files, you can uncheck them (if they're not modified). If you want to keep a lock on a file you've modified, you have to enable the Keep locks checkbox before you commit your changes.

To release a lock manually, select the file(s) in your working copy for which you want to release the lock, then select the command TortoiseSVNRelease Lock There is nothing further to enter so TortoiseSVN will contact the repository and release the locks. You can also use this command on a folder to release all locks recursively.

Checking Lock Status

Figure 4.42. The Check for Modifications Dialog

The Check for Modifications Dialog


To see what locks you and others hold, you can use TortoiseSVNCheck for Modifications.... Locally held lock tokens show up immediately. To check for locks held by others (and to see if any of your locks are broken or stolen) you need to click on Check Repository.

From the context menu here, you can also get and release locks, as well as breaking and stealing locks held by others.

Avoid Breaking and Stealing Locks

If you break or steal someone else's lock without telling them, you could potentially cause loss of work. If you are working with unmergeable file types and you steal someone else's lock, once you release the lock they are free to check in their changes and overwrite yours. Subversion doesn't lose data, but you have lost the team-working protection that locking gave you.

Making Non-locked Files Read-Only

As mentioned above, the most effective way to use locking is to set the svn:needs-lock property on files. Refer to the section called “Project Settings” for instructions on how to set properties. Files with this property set will always be checked out and updated with the read-only flag set unless your working copy holds a lock.

As a reminder, TortoiseSVN uses a special overlay to indicate this.

If you operate a policy where every file has to be locked then you may find it easier to use Subversion's auto-props feature to set the property automatically every time you add new files. Read the section called “Automatic property setting” for further information.

The Locking Hook Scripts

When you create a new repository with Subversion 1.2 or higher, four hook templates are created in the repository hooks directory. These are called before and after getting a lock, and before and after releasing a lock.

It is a good idea to install a post-lock and post-unlock hook script on the server which sends out an email indicating the file which has been locked. With such a script in place, all your users can be notified if someone locks/unlocks a file. You can find an example hook script hooks/post-lock.tmpl in your repository folder.

You might also use hooks to disallow breaking or stealing of locks, or perhaps limit it to a named administrator. Or maybe you want to email the owner when one of their locks is broken or stolen.

Read the section called “Server side hook scripts” to find out more.

Creating and Applying Patches

For open source projects (like this one) everyone has read access to the repository, and anyone can make a contribution to the project. So how are those contributions controlled? If just anyone could commit changes, the project would be permanently unstable and probably permanently broken. In this situation the change is managed by submitting a patch file to the development team, who do have write access. They can review the patch first, and then either submit it to the repository or reject it back to the author.

Patch files are simply Unified-Diff files showing the differences between your working copy and the base revision.

Creating a Patch File

First you need to make and test your changes. Then instead of using TortoiseSVNCommit... on the parent folder, you select TortoiseSVNCreate Patch...

Figure 4.43. The Create Patch dialog

The Create Patch dialog

you can now select the files you want included in the patch, just as you would with a full commit. This will produce a single file containing a summary of all the changes you have made to the selected files since the last update from the repository.

The columns in this dialog can be customized in the same way as the columns in the Check for modifications dialog. Read the section called “Local and Remote Status” for further details.

You can produce separate patches containing changes to different sets of files. Of course, if you create a patch file, make some more changes to the same files and then create another patch, the second patch file will include both sets of changes.

Just save the file using a filename of your choice. Patch files can have any extension you like, but by convention they should use the .patch or .diff extension. You are now ready to submit your patch file.

You can also save the patch to the clipboard instead of to a file. You might want to do this so that you can paste it into an email for review by others. Or if you have two working copies on one machine and you want to transfer changes from one to the other, a patch on the clipboard is a convenient way of doing this.

Applying a Patch File

Patch files are applied to your working copy. This should be done from the same folder level as was used to create the patch. If you are not sure what this is, just look at the first line of the patch file. For example, if the first file being worked on was doc/source/english/chapter1.xml and the first line in the patch file is Index: english/chapter1.xml then you need to apply the patch to the doc/source/ folder. However, provided you are in the correct working copy, if you pick the wrong folder level, TortoiseSVN will notice and suggest the correct level.

In order to apply a patch file to your working copy, you need to have at least read access to the repository. The reason for this is that the merge program must reference the changes back to the revision against which they were made by the remote developer.

From the context menu for that folder, click on TortoiseSVNApply Patch... This will bring up a file open dialog allowing you to select the patch file to apply. By default only .patch or .diff files are shown, but you can opt for “All files”. If you previously saved a patch to the clipboard, you can use Open from clipboard... in the file open dialog. Note that this option only appears if you saved the patch to the clipboard using TortoiseSVNCreate Patch.... Copying a patch to the clipboard from another app will not make the button appear.

Alternatively, if the patch file has a .patch or .diff extension, you can right click on it directly and select TortoiseSVNApply Patch.... In this case you will be prompted to enter a working copy location.

These two methods just offer different ways of doing the same thing. With the first method you select the WC and browse to the patch file. With the second you select the patch file and browse to the WC.

Once you have selected the patch file and working copy location, TortoiseMerge runs to merge the changes from the patch file with your working copy. A small window lists the files which have been changed. Double click on each one in turn, review the changes and save the merged files.

The remote developer's patch has now been applied to your working copy, so you need to commit to allow everyone else to access the changes from the repository.

Who Changed Which Line?

Sometimes you need to know not only what lines have changed, but also who exactly changed specific lines in a file. That's when the TortoiseSVNBlame... command, sometimes also referred to as annotate command comes in handy.

This command lists, for every line in a file, the author and the revision the line was changed.

Blame for Files

Figure 4.44. The Annotate / Blame Dialog

The Annotate / Blame Dialog


If you're not interested in changes from earlier revisions you can set the revision from which the blame should start. Set this to 1, if you want the blame for every revision.

By default the blame file is viewed using TortoiseBlame, which highlights the different revisions to make it easier to read. If you wish to print or edit the blame file, select Use Text viewer to view blames

You can specify the way that line ending and whitespace changes are handled. These options are described in the section called “Line-end and Whitespace Options”. The default behaviour is to treat all whitespace and line-end differences as real changes, but if you want to ignore an indentation change and find the original author, you can choose an appropriate option here.

Once you press OK TortoiseSVN starts retrieving the data to create the blame file. Please note: This can take several minutes to finish, depending on how much the file has changed and of course your network connection to the repository. Once the blame process has finished the result is written into a temporary file and you can view the results.

Figure 4.45. TortoiseBlame

TortoiseBlame


TortoiseBlame, which is included with TortoiseSVN, makes the blame file easier to read. When you hover the mouse over a line in the blame info column, all lines with the same revision are shown with a darker background. Lines from other revisions which were changed by the same author are shown with a light background. The colouring may not work as clearly if you have your display set to 256 colour mode.

If you left click on a line, all lines with the same revision are highlighted, and lines from other revisions by the same author are highlighted in a lighter colour. This highlighting is sticky, allowing you to move the mouse without losing the highlights. Click on that revision again to turn off highlighting.

The revision comments (log message) are shown in a hint box whenever the mouse hovers over the blame info column. If you want to copy the log message for that revision, use the context menu which appears when you right click on the blame info column.

You can search within the Blame report using EditFind.... This allows you to search for revision numbers, authors and the content of the file itself. Log messages are not included in the search - you should use the Log Dialog to search those.

You can also jump to a specific line number using EditGo To Line....

When the mouse is over the blame info columns, a context menu is available which helps with comparing revisions and examining history, using the revision number of the line under the mouse as a reference. Context menuBlame previous revision generates a blame report for the same file, but using the previous revision as the upper limit. This gives you the blame report for the state of the file just before the line you are looking at was last changed. Context menuShow changes starts your diff viewer, showing you what changed in the referenced revision. Context menuShow log displays the revision log dialog starting with the referenced revision.

If you need a better visual indicator of where the oldest and newest changes are, select ViewColor age of lines. This will use a colour gradient to show newer lines in red and older lines in blue. The default colouring is quite light, but you can change it using the TortoiseBlame settings.

If you are using Merge Tracking, where lines have changed as a result of merging from another path, TortoiseBlame will show the revision and author of the last change in the original file rather than the revision where the merge took place. These lines are indicated by showing the revision and author in italics. If you do not want merged lines shown in this way, uncheck the Include merge info checkbox.

If you want to see the paths involved in the merge, select ViewMerge paths.

The settings for TortoiseBlame can be accessed using TortoiseSVNSettings... on the TortoiseBlame tab. Refer to the section called “TortoiseBlame Settings”.

Blame Differences

One of the limitations of the Blame report is that it only shows the file as it was in a particular revision, and shows the last person to change each line. Sometimes you want to know what change was made, as well as who made it. What you need here is a combination of the diff and blame reports.

The revision log dialog includes several options which allow you to do this.

Blame Revisions

In the top pane, select 2 revisions, then select Context menuBlame revisions. This will fetch the blame data for the 2 revisions, then use the diff viewer to compare the two blame files.

Blame Changes

Select one revision in the top pane, then pick one file in the bottom pane and select Context menuBlame changes. This will fetch the blame data for the selected revision and the previous revision, then use the diff viewer to compare the two blame files.

Compare and Blame with Working BASE

Show the log for a single file, and in the top pane, select a single revision, then select Context menuCompare and Blame with Working BASE. This will fetch the blame data for the selected revision, and for the file in the working BASE, then use the diff viewer to compare the two blame files.

The Repository Browser

Sometimes you need to work directly on the repository, without having a working copy. That's what the Repository Browser is for. Just as the explorer and the icon overlays allow you to view your working copy, so the Repository Browser allows you to view the structure and status of the repository.

Figure 4.46. The Repository Browser

The Repository Browser


With the Repository Browser you can execute commands like copy, move, rename, ... directly on the repository.

The repository browser looks very similar to the Windows explorer, except that it is showing the content of the repository at a particular revision rather than files on your computer. In the left pane you can see a directory tree, and in the right pane are the contents of the selected directory. At the top of the Repository Browser Window you can enter the URL of the repository and the revision you want to browse.

Just like Windows explorer, you can click on the column headings in the right pane if you want to set the sort order. And as in explorer there are context menus available in both panes.

The context menu for a file allows you to:

  • Open the selected file, either with the default viewer for that file type, or with a program you choose.

  • Save an unversioned copy of the file to your hard drive.

  • Show the revision log for that file, or show a graph of all revisions so you can see where the file came from.

  • Blame the file, to see who changed which line and when.

  • Delete or rename the file.

  • Make a copy of the file, either to a different part of the repository, or to a working copy rooted in the same repository.

  • View/Edit the file's properties.

The context menu for a folder allows you to:

  • Show the revision log for that folder, or show a graph of all revisions so you can see where the folder came from.

  • Export the folder to a local unversioned copy on your hard drive.

  • Checkout the folder to produce a local working copy on your hard drive.

  • Create a new folder in the repository.

  • Add files or folders directly to the repository.

  • Delete or rename the folder.

  • Make a copy of the folder, either to a different part of the repository, or to a working copy rooted in the same repository. This can also be used to create a branch/tag without the need to have a working copy checked out.

  • View/Edit the folder's properties.

  • Mark the folder for comparison. A marked folder is shown in bold.

  • Compare the folder with a previously marked folder, either as a unified diff, or as a list of changed files which can then be visually diffed using the default diff tool. This can be particularly useful for comparing two tags, or trunk and branch to see what changed.

If you select two folders in the right pane, you can view the differences either as a unified-diff, or as a list of files which can be visually diffed using the default diff tool.

If you select multiple folders in the right pane, you can checkout all of them at once into a common parent folder.

If you select 2 tags which are copied from the same root (typically /trunk/), you can use Context MenuShow Log... to view the list of revisions between the two tag points.

You can use F5 to refresh the view as usual. This will refresh everything which is currently displayed. If you want to pre-fetch or refresh the information for nodes which have not been opened yet, use Ctrl-F5. After that, expanding any node will happen instantly without a network delay while the information is fetched.

You can also use the repository browser for drag-and-drop operations. If you drag a folder from explorer into the repo-browser, it will be imported into the repository. Note that if you drag multiple items, they will be imported in separate commits.

If you want to move an item within the repository, just left drag it to the new location. If you want to create a copy rather than moving the item, Ctrl-left drag instead. When copying, the cursor has a “plus” symbol on it, just as it does in Explorer.

If you want to copy/move a file or folder to another location and also give it a new name at the same time, you can right drag or Ctrl-right drag the item instead of using left drag. In that case, a rename dialog is shown where you can enter a new name for the file or folder.

Whenever you make changes in the repository using one of these methods, you will be presented with a log message entry dialog. If you dragged something by mistake, this is also your chance to cancel the action.

Sometimes when you try to open a path you will get an error message in place of the item details. This might happen if you specified an invalid URL, or if you don't have access permission, or if there is some other server problem. If you need to copy this message to include it in an email, just right click on it and use Context MenuCopy error message to clipboard, or simply use Ctrl+C.

Revision Graphs

Figure 4.47. A Revision Graph

A Revision Graph


Sometimes you need to know where branches and tags were taken from the trunk, and the ideal way to view this sort of information is as a graph or tree structure. That's when you need to use TortoiseSVNRevision Graph...

This command analyses the revision history and attempts to create a tree showing the points at which copies were taken, and when branches/tags were deleted.

Important

In order to generate the graph, TortoiseSVN must fetch all log messages from the repository root. Needless to say this can take several minutes even with a repository of a few thousand revisions, depending on server speed, network bandwidth, etc. If you try this with something like the Apache project which currently has over 500,000 revisions you could be waiting for some time.

The good news is that if you are using log caching, you only have to suffer this delay once. After that, log data is held locally. Log caching is enabled in TortoiseSVN's settings.

Revision Graph Nodes

Each revision graph node represents a revision in the repository where something changed in the tree you are looking at. Different types of node can be distinguished by shape and colour. The shapes are fixed, but colours can be set using TortoiseSVNSettings

Added or copied items

Items which have been added, or created by copying another file/folder are shown using a rounded rectangle. The default colour is green. Tags and trunks are treated as a special case and use a different shade, depending on the TortoiseSVNSettings

Deleted items

Deleted items eg. a branch which is no longer required, are shown using an octagon (rectangle with corners cut off). The default colour is red.

Renamed items

Renamed items are also shown using an octagon, but the default colour is blue.

Branch tip revision

The graph is normally restricted to showing branch points, but it is often useful to be able to see the respective HEAD revision for each branch too. If you select Show HEAD revisions, each HEAD revision nodes will be shown as an ellipse. Note that HEAD here refers to the last revision committed on that path, not to the HEAD revision of the repository.

Working copy revision

If you invoked the revision graph from a working copy, you can opt to show the BASE revision on the graph using Show WC revision, which marks the BASE node with a bold outline.

Modified working copy

If you invoked the revision graph from a working copy, you can opt to show an additional node representing your modified working copy using Show WC modifications. This is an elliptical node with a bold outline in red by default.

Normal item

All other items are shown using a plain rectangle.

Note that by default the graph only shows the points at which items were added, copied or deleted. Showing every revision of a project will generate a very large graph for non-trivial cases. If you really want to see all revisions where changes were made, there is an option to do this in the View menu and on the toolbar.

The default view (grouping off) places the nodes such that their vertical position is in strict revision order, so you have a visual cue for the order in which things were done. Where two nodes are in the same column the order is very obvious. When two nodes are in adjacent columns the offset is much smaller because there is no need to prevent the nodes from overlapping, and as a result the order is a little less obvious. Such optimisations are necessary to keep complex graphs to a reasonable size. Please note that this ordering uses the edge of the node on the older side as a reference, i.e. the bottom edge of the node when the graph is shown with oldest node at the bottom. The reference edge is significant because the node shapes are not all the same height.

Changing the View

Because a revision graph is often quite complex, there are a number of features which can be used to tailor the view the way you want it. These are available in the View menu and from the toolbar.

Group branches

The default behavior (grouping off) has all rows sorted strictly by revision. As a result, long-living branches with sparse commits occupy a whole column for only a few changes and the graph becomes very broad.

This mode groups changes by branch, so that there is no global revision ordering: Consecutive revisions on a branch will be shown in (often) consecutive lines. Sub-branches, however, are arranged in such a way that later branches will be shown in the same column above older branches to keep the graph slim. As a result, a given row may contain changes from different revisions.

Oldest on top

Normally the graph shows the oldest revision at the bottom, and the tree grows upwards. Use this option to grow down from the top instead.

Align trees on top

When a graph is broken into several smaller trees, the trees may appear either in natural revision order, or aligned at the bottom of the window, depending on whether you are using the Group Branches option. Use this option to grow all trees down from the top instead.

Reduce cross lines

If the layout of the graph has produced a lot of crossing lines, use this option to clean it up. This may make the layout columns appear in less logical places, for example in a diagonal line rather than a column, and the graph may require a larger area to draw.

Differential path names

Long path names can take a lot of space and make the node boxes very large. Use this option to show only the changed part of a path, replacing the common part with dots. E.g. if you create a branch /branches/1.2.x/doc/html from /trunk/doc/html the branch could be shown in compact form as /branches/1.2.x/.. because the last two levels, doc and html, did not change.

Show all revisions

This does just what you expect and shows every revision where something (in the tree that you are graphing) has changed. For long histories this can produce a truly huge graph.

Show HEAD revisions

This ensures that the latest revision on every branch is always shown on the graph.

Exact copy sources

When a branch/tag is made, the default behaviour is to show the branch as taken from the last node where a change was made. Strictly speaking this is inaccurate since the branches are often made from the current HEAD rather than a specific revision. So it is possible to show the more correct (but less useful) revision that was used to create the copy. Note that this revision may be younger than the HEAD revision of the source branch.

Fold tags

When a project has many tags, showing every tag as a separate node on the graph takes a lot of space and obscures the more interesting development branch structure. At the same time you may need to be able to access the tag content easily so that you can compare revisions. This option hides the nodes for tags and shows them instead in the tooltip for the node that they were copied from. A tag icon on the right side of the source node indicates that tags were made.

Hide deleted paths

Hides paths which are no longer present at the HEAD revision of the repository, e.g. deleted branches.

Hide unchanged branches

Hides branches where no changes were committed to the respective file or sub-folder. This does not necessarily indicate that the branch was not used, just that no changes were made to this part of it.

Show WC revision

Marks the revision on the graph which corresponds to the update revision of the item you fetched the graph for. If you have just updated, this will be HEAD, but if others have committed changes since your last update your WC may be a few revisions lower down. The node is marked by giving it a bold outline.

Show WC modifications

If your WC contains local changes, this option draws it as a separate elliptical node, linked back to the node that your WC was last updated to. The default outline colour is red. You may need to refresh the graph using F5 to capture recent changes.

Filter

Sometimes the revision graph contains more revisions than you want to see. This option opens a dialog which allows you to restrict the range of revisions displayed, and to hide particular paths by name.

Tree stripes

Where the graph contains several trees, it is sometimes useful to use alternating colours on the background to help distinguish between trees.

Show overview

Shows a small picture of the entire graph, with the current view window as a rectangle which you can drag. This allows you to navigate the graph more easily. Note that for very large graphs the overview may become useless due to the extreme zoom factor and will therefore not be shown in such cases.

Using the Graph

To make it easier to navigate a large graph, use the overview window. This shows the entire graph in a small window, with the currently displayed portion highlighted. You can drag the highlighted area to change the displayed region.

The revision date, author and comments are shown in a hint box whenever the mouse hovers over a revision box.

If you select two revisions (Use Ctrl-left click), you can use the context menu to show the differences between these revisions. You can choose to show differences as at the branch creation points, but usually you will want to show the differences at the branch end points, i.e. at the HEAD revision.

You can view the differences as a Unified-Diff file, which shows all differences in a single file with minimal context. If you opt to Context MenuCompare Revisions you will be presented with a list of changed files. Double click on a file name to fetch both revisions of the file and compare them using the visual difference tool.

If you right click on a revision you can use Context MenuShow Log to view the history.

You can also merge changes in the selected revision(s) into a different working copy. A folder selection dialog allows you to choose the working copy to merge into, but after that there is no confirmation dialog, nor any opportunity to try a test merge. It is a good idea to merge into an unmodified working copy so that you can revert the changes if it doesn't work out! This is a useful feature if you want to merge selected revisions from one branch to another.

Learn to Read the Revision Graph

First-time users may be surprised by the fact that the revision graph shows something that does not match the user's mental model. If a revision changes multiple copies or branches of a file or folder, for instance, then there will be multiple nodes for that single revision. It is a good practice to start with the leftmost options in the toolbar and customize the graph step-by-step until it comes close to your mental model.

All filter options try lose as little information as possible. That may cause some nodes to change their color, for instance. Whenever the result is unexpected, undo the last filter operation and try to understand what is special about that particular revision or branch. In most cases, the initially expected outcome of the filter operation would either be inaccurate or misleading.

Refreshing the View

If you want to check the server again for newer information, you can simply refresh the view using F5. If you are using the log cache (enabled by default), this will check the repository for newer commits and fetch only the new ones. If the log cache was in offline mode, this will also attempt to go back online.

If you are using the log cache and you think the message content or author may have changed, you should use the log dialog to refresh the messages you need. Since the revision graph works from the repository root, we would have to invalidate the entire log cache, and refilling it could take a very long time.

Pruning Trees

A large tree can be difficult to navigate and sometimes you will want to hide parts of it, or break it down into a forest of smaller trees. If you hover the mouse over the point where a node link enters or leaves the node you will see one or more popup buttons which allow you to do this.

Click on the minus button to collapse the attached sub-tree.

Click on the plus button to expand a collapsed tree. When a tree has been collapsed, this button remains visible to indicate the hidden sub-tree.

Click on the cross button to split the attached sub-tree and show it as a separate tree on the graph.

Click on the circle button to reattach a split tree. When a tree has been split away, this button remains visible to indicate that there is a separate sub-tree.

Click on the graph background for the main context menu, which offers options to Expand all and Join all. If no branch has been collapsed or split, the context menu will not be shown.

Exporting a Subversion Working Copy

Sometimes you may want a copy of your working tree without any of those .svn directories, e.g. to create a zipped tarball of your source, or to export to a web server. Instead of making a copy and then deleting all those .svn directories manually, TortoiseSVN offers the command TortoiseSVNExport.... Exporting from a URL and exporting from a working copy are treated slightly differently.

Figure 4.48. The Export-from-URL Dialog

The Export-from-URL Dialog


If you execute this command on an unversioned folder, TortoiseSVN will assume that the selected folder is the target, and open a dialog for you to enter the URL and revision to export from. This dialog has options to export only the top level folder, to omit external references, and to override the line end style for files which have the svn:eol-style property set.

Of course you can export directly from the repository too. Use the Repository Browser to navigate to the relevant subtree in your repository, then use Context MenuExport. You will get the Export from URL dialog described above.

If you execute this command on your working copy you'll be asked for a place to save the clean working copy without the .svn folders. By default, only the versioned files are exported, but you can use the Export unversioned files too checkbox to include any other unversioned files which exist in your WC and not in the repository. External references using svn:externals can be omitted if required.

Another way to export from a working copy is to right drag the working copy folder to another location and choose Context MenuSVN Export here or Context MenuSVN Export all here. The second option includes the unversioned files as well.

When exporting from a working copy, if the target folder already contains a folder of the same name as the one you are exporting, you will be given the option to overwrite the existing content, or to create a new folder with an automatically generated name, eg. Target (1).

Exporting single files

The export dialog does not allow exporting single files, even though Subversion can.

To export single files with TortoiseSVN, you have to use the repository browser (the section called “The Repository Browser”). Simply drag the file(s) you want to export from the repository browser to where you want them in the explorer, or use the context menu in the repository browser to export the files.

Exporting a Change Tree

If you want to export a copy of your project tree structure but containing only the files which have changed in a particular revision, or between any two revisions, use the compare revisions feature described in the section called “Comparing Folders”.

Removing a working copy from version control

Sometimes you have a working copy which you want to convert back to a normal folder without the .svn directories. What you really need is an export-in-place command, that just removes the control directories rather than generating a new clean directory tree.

The answer is surprisingly simple - export the folder to itself! TortoiseSVN detects this special case and asks if you want to make the working copy unversioned. If you answer yes the control directories will be removed and you will have a plain, unversioned directory tree.

Relocating a working copy

Figure 4.49. The Relocate Dialog

The Relocate Dialog


If your repository has for some reason changed it's location (IP/URL). Maybe you're even stuck and can't commit and you don't want to checkout your working copy again from the new location and to move all your changed data back into the new working copy, TortoiseSVNRelocate is the command you are looking for. It basically does very little: it scans all entries files in the .svn folder and changes the URL of the entries to the new value.

You may be surprised to find that TortoiseSVN contacts the repository as part of this operation. All it is doing is performing some simple checks to make sure that the new URL really does refer to the same repository as the existing working copy.

Warning

This is a very infrequently used operation. The relocate command is only used if the URL of the repository root has changed. Possible reasons are:

  • The IP address of the server has changed.

  • The protocol has changed (e.g. http:// to https://).

  • The repository root path in the server setup has changed.

Put another way, you need to relocate when your working copy is referring to the same location in the same repository, but the repository itself has moved.

It does not apply if:

  • You want to move to a different Subversion repository. In that case you should perform a clean checkout from the new repository location.

  • You want to switch to a different branch or directory within the same repository. To do that you should use TortoiseSVNSwitch.... Read the section called “To Checkout or to Switch...” for more information.

If you use relocate in either of the cases above, it will corrupt your working copy and you will get many unexplainable error messages while updating, committing, etc. Once that has happened, the only fix is a fresh checkout.

Integration with Bug Tracking Systems / Issue Trackers

It is very common in Software Development for changes to be related to a specific bug or issue ID. Users of bug tracking systems (issue trackers) would like to associate the changes they make in Subversion with a specific ID in their issue tracker. Most issue trackers therefore provide a pre-commit hook script which parses the log message to find the bug ID with which the commit is associated. This is somewhat error prone since it relies on the user to write the log message properly so that the pre-commit hook script can parse it correctly.

TortoiseSVN can help the user in two ways:

  1. When the user enters a log message, a well defined line including the issue number associated with the commit can be added automatically. This reduces the risk that the user enters the issue number in a way the bug tracking tools can't parse correctly.

    Or TortoiseSVN can highlight the part of the entered log message which is recognized by the issue tracker. That way the user knows that the log message can be parsed correctly.

  2. When the user browses the log messages, TortoiseSVN creates a link out of each bug ID in the log message which fires up the browser to the issue mentioned.

Adding Issue Numbers to Log Messages

You can integrate a bug tracking tool of your choice in TortoiseSVN. To do this, you have to define some properties, which start with bugtraq:. They must be set on Folders: (the section called “Project Settings”)

There are two ways to integrate TortoiseSVN with issue trackers. One is based on simple strings, the other is based on regular expressions. The properties used by both approaches are:

bugtraq:url

Set this property to the URL of your bug tracking tool. It must be properly URI encoded and it has to contain %BUGID%. %BUGID% is replaced with the Issue number you entered. This allows TortoiseSVN to display a link in the log dialog, so when you are looking at the revision log you can jump directly to your bug tracking tool. You do not have to provide this property, but then TortoiseSVN shows only the issue number and not the link to it. e.g the TortoiseSVN project is using http://issues.tortoisesvn.net/?do=details&id=%BUGID%

You can also use relative URLs instead of absolute ones. This is useful when your issue tracker is on the same domain/server as your source repository. In case the domain name ever changes, you don't have to adjust the bugtraq:url property. There are two ways to specify a relative URL:

If it begins with the string ^/ it is assumed to be relative to the repository root. For example, ^/../?do=details&id=%BUGID% will resolve to http://tortoisesvn.net/?do=details&id=%BUGID% if your repository is located on http://tortoisesvn.net/svn/trunk/.

A URL beginning with the string / is assumed to be relative to the server's hostname. For example /?do=details&id=%BUGID% will resolve to http://tortoisesvn.net/?do=details&id=%BUGID% if your repository is located anywhere on http://tortoisesvn.net.

bugtraq:warnifnoissue

Set this to true, if you want TortoiseSVN to warn you because of an empty issue-number text field. Valid values are true/false. If not defined, false is assumed.

Issue Number in Text Box

In the simple approach, TortoiseSVN shows the user a separate input field where a bug ID can be entered. Then a separate line is appended/prepended to the log message the user entered.

bugtraq:message

This property activates the bug tracking system in Input field mode. If this property is set, then TortoiseSVN will prompt you to enter an issue number when you commit your changes. It's used to add a line at the end of the log message. It must contain %BUGID%, which is replaced with the issue number on commit. This ensures that your commit log contains a reference to the issue number which is always in a consistent format and can be parsed by your bug tracking tool to associate the issue number with a particular commit. As an example you might use Issue : %BUGID%, but this depends on your Tool.

bugtraq:append

This property defines if the bug-ID is appended (true) to the end of the log message or inserted (false) at the start of the log message. Valid values are true/false. If not defined, true is assumed, so that existing projects don't break.

bugtraq:label

This text is shown by TortoiseSVN on the commit dialog to label the edit box where you enter the issue number. If it's not set, Bug-ID / Issue-Nr: will be displayed. Keep in mind though that the window will not be resized to fit this label, so keep the size of the label below 20-25 characters.

bugtraq:number

If set to true only numbers are allowed in the issue-number text field. An exception is the comma, so you can comma separate several numbers. Valid values are true/false. If not defined, true is assumed.

Issue Numbers Using Regular Expressions

In the approach with regular expressions, TortoiseSVN doesn't show a separate input field but marks the part of the log message the user enters which is recognized by the issue tracker. This is done while the user writes the log message. This also means that the bug ID can be anywhere inside a log message! This method is much more flexible, and is the one used by the TortoiseSVN project itself.

bugtraq:logregex

This property activates the bug tracking system in Regex mode. It contains either a single regular expressions, or two regular expressions separated by a newline.

If two expressions are set, then the first expression is used as a pre-filter to find expressions which contain bug IDs. The second expression then extracts the bare bug IDs from the result of the first regex. This allows you to use a list of bug IDs and natural language expressions if you wish. e.g. you might fix several bugs and include a string something like this: “This change resolves issues #23, #24 and #25

If you want to catch bug IDs as used in the expression above inside a log message, you could use the following regex strings, which are the ones used by the TortoiseSVN project: [Ii]ssues?:?(\s*(,|and)?\s*#\d+)+ and (\d+)

The first expression picks out “issues #23, #24 and #25” from the surrounding log message. The second regex extracts plain decimal numbers from the output of the first regex, so it will return “23”, “24” and “25” to use as bug IDs.

Breaking the first regex down a little, it must start with the word “issue”, possibly capitalised. This is optionally followed by an “s” (more than one issue) and optionally a colon. This is followed by one or more groups each having zero or more leading whitespace, an optional comma or “and” and more optional space. Finally there is a mandatory “#” and a mandatory decimal number.

If only one expression is set, then the bare bug IDs must be matched in the groups of the regex string. Example: [Ii]ssue(?:s)? #?(\d+) This method is required by a few issue trackers, e.g. trac, but it is harder to construct the regex. We recommend that you only use this method if your issue tracker documentation tells you to.

If you are unfamiliar with regular expressions, take a look at the introduction at http://en.wikipedia.org/wiki/Regular_expression , and the online documentation and tutorial at http://www.regular-expressions.info/ .

If both the bugtraq:message and bugtraq:logregex properties are set, logregex takes precedence.

Tip

Even if you don't have an issue tracker with a pre-commit hook parsing your log messages, you still can use this to turn the issues mentioned in your log messages into links!

And even if you don't need the links, the issue numbers show up as a separate column in the log dialog, making it easier to find the changes which relate to a particular issue.

Some tsvn: properties require a true/false value. TortoiseSVN also understands yes as a synonym for true and no as a synonym for false.

Set the Properties on Folders

These properties must be set on folders for the system to work. When you commit a file or folder the properties are read from that folder. If the properties are not found there, TortoiseSVN will search upwards through the folder tree to find them until it comes to an unversioned folder, or the tree root (eg. C:\) is found. If you can be sure that each user checks out only from e.g trunk/ and not some sub-folder, then it's enough if you set the properties on trunk/. If you can't be sure, you should set the properties recursively on each sub-folder. A property setting deeper in the project hierarchy overrides settings on higher levels (closer to trunk/).

For project properties only, i.e. tsvn:, bugtraq: and webviewer: you can use the Recursive checkbox to set the property to all sub-folders in the hierarchy, without also setting it on all files.

When you add new sub-folders to a working copy using TortoiseSVN, any project properties present in the parent folder will automatically be added to the new child folder too.

No Issue Tracker Information from Repository Browser

Because the issue tracker integration depends upon accessing subversion properties, you will only see the results when using a checked out working copy. Fetching properties remotely is a slow operation, so you will not see this feature in action from the repo browser unless you started the repo browser from your working copy. If you started the repo browser by entering the URL of the repository you won't see this feature.

For the same reason, project properties will not be propagated automatically when a child folder is added using the repo browser.

This issue tracker integration is not restricted to TortoiseSVN; it can be used with any Subversion client. For more information, read the full Issue Tracker Integration Specification in the TortoiseSVN source repository. (the section called “TortoiseSVN is free!” explains how to access the repository).

Getting Information from the Issue Tracker

The previous section deals with adding issue information to the log messages. But what if you need to get information from the issue tracker? The commit dialog has a COM interface which allows integration an external program that can talk to your tracker. Typically you might want to query the tracker to get a list of open issues assigned to you, so that you can pick the issues that are being addressed in this commit.

Any such interface is of course highly specific to your issue tracker system, so we cannot provide this part, and describing how to create such a program is beyond the scope of this manual. The interface definition and sample plugins in C# and C++/ATL can be obtained from the contrib folder in the TortoiseSVN repository . (the section called “TortoiseSVN is free!” explains how to access the repository). A summary of the API is also given in Chapter 6, IBugtraqProvider interface Another (working) example plugin in C# is Gurtle which implements the required COM interface to interact with the Google Code issue tracker.

For illustration purposes, let's suppose that your system administrator has provided you with an issue tracker plugin which you have installed, and that you have set up some of your working copies to use the plugin in TortoiseSVN's settings dialog. When you open the commit dialog from a working copy to which the plugin has been assigned, you will see a new button at the top of the dialog.

Figure 4.50. Example issue tracker query dialog

Example issue tracker query dialog


In this example you can select one or more open issues. The plugin can then generate specially formatted text which it adds to your log message.

Integration with Web-based Repository Viewers

There are several web-based repository viewers available for use with Subversion such as ViewVC and WebSVN . TortoiseSVN provides a means to link with these viewers.

You can integrate a repo viewer of your choice in TortoiseSVN. To do this, you have to define some properties which define the linkage. They must be set on Folders: (the section called “Project Settings”)

webviewer:revision

Set this property to the URL of your repo viewer to view all changes in a specific revision. It must be properly URI encoded and it has to contain %REVISION%. %REVISION% is replaced with the revision number in question. This allows TortoiseSVN to display a context menu entry in the log dialog Context MenuView revision in webviewer

webviewer:pathrevision

Set this property to the URL of your repo viewer to view changes to a specific file in a specific revision. It must be properly URI encoded and it has to contain %REVISION% and %PATH%. %PATH% is replaced with the path relative to the repository root. This allows TortoiseSVN to display a context menu entry in the log dialog Context MenuView revision and path in webviewer For example, if you right-click in the log dialog bottom pane on a file entry /trunk/src/file then the %PATH% in the URL will be replaced with /trunk/src/file.

You can also use relative URLs instead of absolute ones. This is useful in case your web viewer is on the same domain/server as your source repository. In case the domain name ever changes, you don't have to adjust the webviewer:revision and webviewer:pathrevision property. The format is the same as for the bugtraq:url property. See the section called “Integration with Bug Tracking Systems / Issue Trackers”.

Set the Properties on Folders

These properties must be set on folders for the system to work. When you commit a file or folder the properties are read from that folder. If the properties are not found there, TortoiseSVN will search upwards through the folder tree to find them until it comes to an unversioned folder, or the tree root (eg. C:\) is found. If you can be sure that each user checks out only from e.g trunk/ and not some sub-folder, then it's enough if you set the properties on trunk/. If you can't be sure, you should set the properties recursively on each sub-folder. A property setting deeper in the project hierarchy overrides settings on higher levels (closer to trunk/).

For project properties only, i.e. tsvn:, bugtraq: and webviewer: you can use the Recursive checkbox to set the property to all sub-folders in the hierarchy, without also setting it on all files.

When you add new sub-folders to a working copy using TortoiseSVN, any project properties present in the parent folder will automatically be added to the new child folder too.

Limitations Using the Repository Browser

Because the repo viewer integration depends upon accessing subversion properties, you will only see the results when using a checked out working copy. Fetching properties remotely is a slow operation, so you will not see this feature in action from the repo browser unless you started the repo browser from your working copy. If you started the repo browser by entering the URL of the repository you won't see this feature.

For the same reason, project properties will not be propagated automatically when a child folder is added using the repo browser.

TortoiseSVN's Settings

To find out what the different settings are for, just leave your mouse pointer a second on the editbox/checkbox... and a helpful tooltip will popup.

General Settings

Figure 4.51. The Settings Dialog, General Page

The Settings Dialog, General Page


This dialog allows you to specify your preferred language, and the Subversion-specific settings.

Language