It's a common scenario: you are altering your working code or game assets over several hours or even days. You are in between two releases and the game won't compile due to unfinished changes. Further you no longer have a clue how the old code was shaped because it became overwritten.
There are a few solutions to avoid incompilabilty (does this word exist?) and loss of working code:
- make backup copies for all files which will change
- make a backup of the whole project, regardless what's changing
- disable old code by commenting it out or exclusion by conditional statements
- add version numbers to outdated files, e.g. main.cpp is the latest version, main_001.cpp is the oldest version, main_002.cpp is the second oldest, etc.
- any other method?
These methods are simple. You can easily master your projects with them. But there are more elegant and sophisticated solutions to this. The buzz phrase here is Version Control System (VCS). There are quite a few VCS available for free like Git, CVS or Subversion. I favor Subversion (SVN) because it's free, simple (well, as long as you avoid excessive merging), flexible, has high-quality tools and is well supported. Therefore I want to show you how to set up a simple Subversion system to streamline versioning, fallback management and persistence. There won't be any server stuff, SSL encrypted data flow or rights management. Subversion supports all that but a lone wolf coder/artist does not need that overkill. KISS: Keep it stupid simple!
There is just one drawback: This tutorial is Windows only. Sorry.
Download it here and install it. Restart your machine if you are asked to do so. We will use TortoiseSVN right away.
A Subversion repository is a central directory where all versioned files and their meta data are stored. A repository can have an arbitrary number of sub-directories which can contain source code, images, sound files, documents, etc. It's up to you how you want to structure your VCS. In this example we are going to create only one repository on a hard-drive. You can add further repositories any time.
First we have to choose a location where we want our repository to reside. Think about robustness and security. You may pull out your hair if your hard-drive breaks and your source as well as your repository reside there. Choose an other partition, a physical separated hard-drive or even an other machine for your repositories. Security increases with distance.
Create a conventional directory at your chosen place and name it something like "svn_repository". Right-click the new folder and choose "Create repository here" from the TortoiseSVN context menu:
After clicking OK in the success message box (I hope it worked) you can investigate new files and folders in the repository. Don't change anything there unless you know what you do! README.txt will tell you the same but who reads it anyway?
OK, now we are going to build our very own structure within the new repository. Right-click a free position on the desktop or in an Explorer window (to open the context menu) and choose "Repo-browser" from the TortoiseSVN context menu:
Now enter the address to your repository. I've created it in "C:\test_repository" so I have to enter "file:///C:/test_repository" in the pop-up dialog:
The repository browser shows you the virgin state of your newly created repository. The layout is similar to the Windows Explorer layout: an address bar in the header, a tree view on the left hand side and a directory/file list on the right hand side. Most of its functionality is packed in the context menus. When you open the repository's context menu (right-click) you will see quite a few functions there:
Explaining all these functions here would go beyond this article's scope. I highly recommend reading the help file which you can find it at the bottom of the TortoiseSVN context menu. There is even a full Subversion book available online. You don't have to read everything in these documents. There are just a few essential functions you should understand. We will use many of them here anyway and I will summarize the most important ones in the conclusion.
Link Your Project To Subversion
The next step is importing a project into the repository. Let's say our project is named foobar and simply contains a Visual Studio solution structure:
In the repository browser choose "Add folder..." from the repository's context menu, select the foobar directory, click OK and confirm the log message dialog. Log messages are optional but recommended. They will help you tracing the revision logs. I've entered "import of project foobar".
The foobar directory should be fully imported now. This means the current state of foobar is conserved in the repository. That's nice but it is just a copy of the project in the repository, foobar is not version-controlled yet. For this we have to check out a working copy (WK) of the project. A WK is just a directory fetched from Subversion to work on. In Subversion such a fetch is called checkout. WKs are "supervised" by Subversion and recognize changes. That's the basic difference between a conventional project directory and a WK.
Open the foobar directory's context menu in the repository browser and click "Checkout...". The appearing dialog should already have the correct settings:
Clicking OK will bring up a warning if you want to overwrite the directory. This is OK because it will overwrite the files with their equal copies from the repository. So we click Yes and take a look into the foobar project with Windows Explorer. All files and directories now should have little hooks on their icons. If not, try hitting F5 (view refresh) a few times. TortoiseSVN sometimes does not update the Explorer view immediately so refreshing may be necessary:
If you show hidden files in Windows Explorer you will see hidden directories named ".svn". This is TortoiseSVN's outpost for meta data for the directory it lies in. Don't touch it, leave it alone.
Subversion Shows The Differences
TortoiseSVN overlays the Explorer icons of version-controlled files and directories with a SVN status icon. The two icons you have to know are the green hook and the red exclamation mark. The hook means "the file/directory in this working copy is equal to its repository counterpart" whereas the exclamation mark tells you "this file/directory was changed, it's no longer equal to the repository's state".
That's a big advantage over the simple methods for versioning I've listed at the beginning of this article. You can see immediately which files and directories changed without extra work. Simply alter the files and TortoiseSVN tags the changes.
But there is more. You can even find out what changed within the files. TortoiseSVN natively supports difference viewing for texts and images. To test text difference inspection I've deleted a single character in the projects ReadMe.txt file. Saving the changed file makes the SVN status icon switch over to exclamation mark:
Now we choose "Diff" from the TortoiseSVN context menu of ReadMe.txt:
TortoiseMerge, the default diff-and-merge program of TortoiseSVN, opens and highlights the changed word.
Storing Changes In Repository
So far TortoiseSVN shows us which files and directories changed as well as where exactly the changes are. Now we store the changed file in the repository. In SVN this is called committing. It is the most important aspect of any VCS. Otherwise they just would be diff viewers and repositories would be senseless.
Choose "Commit..." from ReadMe.txt its context menu. The following window opens:
Here you can enter a log message in the first text area. As mentioned earlier it is recommended to describe your changes. Therefore I've entered "deleted one character". The list below shows all files and directories which changed. We commit only ReadMe.txt so just this file is listed. Double-clicking a listed file shows the differences as we already saw before.
Clicking OK updates ReadMe.txt in the repository. A progress window pops up and should finally state "Completed" in the Action column. The new version of ReadMe.txt is stored in the repository now. At this point overwriting or deleting ReadMe.txt (or any other file of the project) is no problem anymore. You can restore any version of the files you've committed from the repository. Every commit you make gets a serial number called revision number. Revisions are the states of your files over time. Let's have a look at the history of events we made so far. Open foobar's TortoiseSVN context menu and click "Show log". The log window should look like this:
The top list shows all revisions foobar has undergone. Revision 1 was the initial import of project foobar into the repository. Revision 2 was the commit of the changed ReadMe.txt file. The centered text area shows the log message of the selected revision while the bottom list shows all files which changed in the selected revision.
The change of ReadMe.txt was just for showing you the diff-view and commit. Now we want to restore the old and correct state of this file. That's as simple as choosing the revision which holds the correct state of the file and overwriting the working copy with it. Open foobar's TortoiseSVN context menu and click "Update to revision...":
This will bring up a small dialog which asks for the revision you want. Select option "Revision", enter 1 and click OK:
The following progress window should list only ReadMe.txt as upated. Close this window and open ReadMe.txt: the word summary was corrected because the file was set back to revision 1, before character u was deleted. That's the way you can restore older versions of your files.
I hope this tutorial gave you an idea how Subversion/TortoiseSVN works and what you can gain from it. You will find many more functions in TortoiseSVN which will improve your working habits. I highly recommend reading the help files coming with TortoiseSVN and the online Subversion book. They are well written and will teach you better than I can do here.
This is a short list of most important functions you will encounter when working with TortoiseSVN:
- Add: Makes an unversioned file/directory version-controlled
- Add folder: Copies a directory from your hard-drive into the repository
- Checkout: Creates a working copy from a directory in the repository on your hard-drive
- Commit: Stores changes in working copy to repository with a new revision number
- Delete: Deletes a file or directory from the repository and/or working copy - use this for version-controlled files/directories instead of standard deletion
- Diff: Shows differences between working copy and last revision
- Diff with previous version: Shows differences between working copy and specific revision
- Rename: Renames a file or directory in repository and/or working copy - use this for version-controlled files/directories instead of standard rename
- Repo-browser: Opens browser for a specified repository
- Revert: Undoes changes by overwriting file/directory with last revision
- Show log: Opens list of revisions including log messages and detailed change overview
- Update: Overwrites file/directory with its latest revision
- Update to revision: Overwrites file/directory with a specific revision