In this article I assume, that you already have the Subversion installed and that your repository is already created and accessible (see Part 2 for how to do that). I will use both command line client (svn) and TortoiseSVN (graphical client for Windows) in parallel to demonstrate multiple ways to do things. In the examples I will use the http: protocol to access Subversion (for which the Apache HTTP server is needed), but you can equally good use the svn: (you need to run Subversion's svnserve server) or file: (with no server) to go through the sample scenarios. The root URL of the repository in my examples will be localhost / repos /sandbox/ (it's the repository created in Part 2 examples).
All the source files used in this article are available in the attached zip file.
The first important command we should get familiar with is help. Both tools have rich help, which assist us to quickly find reference information.
### Command Line
svn help
### Tortoise SVN
Right Click -> TortoiseSVN -> Help
When starting the work with some repository, we usually wan to check, whether the repository URL is correct and to get oriented in the repository structure. With command line client we can use the info and list commands, with Tortoise the easies way is to use the build-in Repo-browser. When using http protocol, there is also the alternative to simply use web browser to examine the repository structure/content.
### Command Line
svn info localhost/repos/sandbox/
and after that
svn list -v localhost/repos/sandbox/
(and eventually -R for recursive listing)
### Tortoise SVN
Right Click -> TortoiseSVN -> Repo-browser -> type in the URL localhost/repos/sandbox/ -> OK
During the above use case the clients might ask for user name/password, if the anonymous read access is not allowed (depending on your access file - as explained in Part 2), in different setup they might ask later - when a write operation is performed. By default the user credentials will be remembered and asked for only once per repository (the credentials are stored in your home folder).
Once we know our repository, we can start by importing our project. Let's assume we have a Java project called Hanoi, which solves the well known Towers of Hanoi problem (http://en.wikipedia.org/wiki/Towers_of_Hanoi). We have the project on our hard disk and we want to put it into Subversion repository. We have two options for importing data - either we just want to place files into version control or we want to place them into version control and turn the existing folders into SVN working copy, without moving the files. Let's go through the both cases. Firstly we will create the recommended project structure (trunk/branches/tags) by import, secondly we will turn the project folder into a working copy. Create the following structure in your temp folder:
Now we will import this structure into SVN.
### Command Line
cd \Temp
svn import structure http:// localhost / repos/sandbox/ -m "Importing the project structure"
The -m MESSAGE is common parameter for SVN commands which write data into the repository - you always have to specify the message. Try to execute the command without -m and see the result.
### Tortoise SVN
Right Click the "structure" folder-> TortoiseSVN -> Import... -> Enter the repository URL localhost/repos/sandbox/ and the commit message -> OK
Now we have the folder structure duplicated in the repository, but there is no connection between the files on our disk and in the repository - it's not a working copy - therefore there is no easy way to propagate changes from the temp folder to the repository.
We will use the other method to import the actual project files, because these are already placed on correct location in our working place and also we want to selectively avoid the import of some files (e.g. compiled binaries). First we will checkout the empty SVN project folder into our actual project (to create working copy), then we will add the necessary files into the version control and finally we will commit them into the repository. The project files are located in folder [1] in the source zip file.
### Command Line
Non recursively checkout the trunk folder into the project root (don't miss the ‘.' in the checkout command)
cd hanoi
svn checkout -N localhost/repos/sandbox/Hanoi/trunk/ .
Now your project is a working copy (there is the .svn folder there). Recursively add src folder into the cource control
svn add src
Non recursively add all other files
svn add -N *.*
Ignore any content inside the bin folder
svn propset svn:ignore "*.*" bin
Commit all changes at once into the repository
svn commit -m "Adding the project content"
### Tortoise SVN
Right Click the "hanoi" folder -> Checkout... -> Enter the URL localhost/repos/sandbox/Hanoi/trunk; check "Only checkout the top folder" -> OK -> Yes (to checkout anyway)
Now your project is a working copy (there is the .svn folder there). Add the files into version control:
Right Click the "hanoi" folder -> TortoiseSVN -> Add... -> uncheck the *.class -> OK
So now all the files, extept the classes in the bin folder are scheduled for addition on commit. Next we tell SVN to forever ignore the content of bin folder:
Go to hanoi\bin\, Right Click Solver.class -> TortoiseSVN -> Add to Ignore List -> *.class
And finally commit all the changes:
Right Click the "hanoi" folder -> SVN Commit... -> Fill in the commit message -> OK
Now you can explore the repository content to see the project files inside and you can also check, that the project folder on your local disk is a Subversion working copy (each folder contains the .svn subfolder). When invoked from inside of working copy, both command line client and Tortoise recognize that and behave accordingly, e.g. they determine the repository location from the working copy.
As now the project is in the repository, multiple people can start working on it. We will simulate that by checking out another working copy, which will represent another user's workspace.
### Command Line
cd \Temp
mkdir bob\hanoi
svn checkout http:// localhost/repos/sandbox/Hanoi/trunk/ bob\hanoi
### Tortoise SVN
Create \Temp\bob\hanoi
Right Click the "hanoi" folder-> SVN Checkout... -> Enter the URL localhost/repos/sandbox/Hanoi/tru (it's probably already preset since the last operation) -> OK
Bob is now going to edit some files. He will add a new class Counter.java and modify the run.bat. You can find the final files in folder 2 of attached sources.
### Command Line
cd \temp\bob\hanoi
First, use svn status to see which files are new and modified, you will get:
? src\Counter.java
M run.bat
which indicates one new file (?) and one modified (M). Note, that the Counter.class in bin folder gets ignored. Now add Counter into the source control:
svn add src\Counter.java
(try svn status gain) and commit
svn commit -m "Adding the counter"
### Tortoise SVN
It's much easier here, since the commit window already does a lot of work for us:
Right Click the "Hanoi" folder-> SVN Commit... -> Enter the commit message and check the checkbox next to Counter.class -> OK
Now we will get back to the first user (Alice, of course), who imported the project. She updates her working copy to get Bob's changes.
### Command Line
cd \temp\hanoi
svn update
### Tortoise SVN
Right Click the "\temp\hanoi" folder-> SVN Update...
In both cases, you will be given overview of what was updated.
The last scenario, which we will go through is branching and merging. Let's assume now, that Bob now has to do some performance optimization of the Counter class, which lasts long and therefore should be done in branch. Firstly, he creates the branch:
### Command Line
svn copy localhost/repos/sandbox/Hanoi/trunk/ localhost/repos/sandbox/Hanoi/branches/performance/ -m "Creating the performance branch"
### Tortoise SVN
Select the Hanoi/trunk folder in the Tortoise Repo-browser -> Right Click -> Copy to... -> Change the URL to http: // localhost/repos/sandbox/Hanoi/branches/performance/ -> OK -> Enter the commit message -> OK
Now the branch is ready and we need a working copy to modify. We can of course checkout the new working copy out of branch, but it is easier to switch the existing WC into branch. Switching has the advantage that it preserves the local modifications (if any). Therefore we can start working on some task and afterwards decide, that this requires branch and switch into the branch together with the changes.
### Command Line
cd \temp\bob\hanoi
svn switch localhost/repos/sandbox/Hanoi/branches/performance/
The command shows all the changes made to the working copy. To verify, that we are really in branch, we can use
svn info
### Tortoise SVN
Right Click on \temp\bob\hanoi -> TortoiseSVN -> Switch... -> Change the URL to localhost/repos/sandbox/Hanoi/branches/performance/ -> OK
The actual changes to Counter.java class are in the folder 3 in sources zip file - you can copy it into the working copy. Of course, this change is far too trivial to be done in branch, but it's good enough as a sample. Now Bob commits the changes and switches his working copy back to trunk:
### Command Line
svn commit -m "Counter optimized"
svn switch localhost/repos/sandbox/Hanoi/trunk/
Notice, that the Counter.java file was updated back to it's trunk content
### Tortoise SVN
Right Click on \temp\bob\hanoi -> TortoiseSVN -> Switch... -> Change the URL to localhost/repos/sandbox/Hanoi/branches/trunk/ -> OK
The last operation to finish the performance optimization is merging the changes back to trunk. This has two steps - first we merge the changes from branch into the trunk working copy and after verifying the result (and merging possible conflicts) we commit the result into the repository.
### Command Line
Firstly, we need to determine revision since which we want to merge the changes - in our case it's the revision in which the branch was created (you can use e.g. svn log command to discover the revision number). In my case, it's revision 5:
svn merge -r 5:HEAD http:// localhost/repos/sandbox/Hanoi/branches/performance/ --dry-run
Firstly we perform just the dry run, which prints all the information, but does not modify any files - we us it to verify correctness of the arguments. After checking the result, we can perform the actual merge:
svn merge -r 5:HEAD localhost/repos/sandbox/Hanoi/branches/performance/
After testing the result, we can commit
svn commit -m "Merging the performance branch"
### Tortoise SVN
Right Click on \temp\bob\hanoi -> TortoiseSVN -> Merge... -> Change the From URL to http:// localhost/repos/sandbox/Hanoi/branches/performance/, use the Show Log to select the From revision (select the first revision, which actually contains the changes). select HEAD as To revision -> Press Dry Run to check the parameters are correct -> press Merge to perform the actual merge.
Now test the merge result and do commit afterwards:
Right Click on \temp\bob\hanoi -> SVN Commit... -> Fill in the commit message -> OK.
Now you can use the svn log or TortoiseSVN Show Log to examine all the changes done today.
And that's all. Today, we have imported project, edited the files, created branch, worked in branch and merged it back to the trunk. It was only the overview of basic operations, we avoided more complex use cases (like conflict resolution) and we also did present only one way to perform each task. However, this initial walk thought should give you the overall feeling of how things work and also the basis to explore the other commands and the options of the commands we have already used.
This is the end of the Part 3 of Subversion series. The next (and last) part will focus on process of migration from other Version Control System to Subversion and also will give some hints for adopting Subversion into the development process.
Michal Dobisek is Software Architect at Polarion Software GmbH. He has experience with CVS, Perforce and Subversion. He has two years experience in using, administering and tweaking Subversion. He holds a Masters degree in Cybernetics from Gerstner Laboratory of the Czech Technical University in Prague.