Getting started with SVN

Note: This post is over a year old. You may want to check later in this blog to see if there is new information.

Yesterday we installed Subversion. We’re going to dive into the command line today, so get comfortable on a machine that has your favorite terminal program on it (I’ll be using iTerm). We’re going to create a test repository and check it out, learning a few svn basics along the way. By the time we’re done, we’ll be all ready to make our blog or website into a repository and check it out on our local machine for editing. BTW, we’re starting with the Terminal because it’s my personal opinion that you shouldn’t use a graphical client until you understand what’s going on at a more basic level. So on with the basics…

Locating Subversion

If you’re using OS X and you’ve installed the binaries, they should be located in /usr/local/bin. If this is not currently in your path, you’ll need to add it. You can verify this by typing “which svn”. If you get a negative response, it’s not in your path. If you get a response other than /usr/local/bin/svn, then you need to check your version and make sure it’s 1.4.3: type “svn --version”.

To add /usr/local/bin to your path, you’ll need to edit your ~/.bash_profile file. Load up the file in your favorite editor, creating it if it doesn’t exist. Add the line:

export PATH=/usr/local/bin:$PATH

to the end of the file. If you know what you’re doing, and you already have a PATH statement, just add /usr/local/bin into the path statement at the beginning. Run the profile by typing:

. .bash_profile

You should now be able to type “svn” at the prompt and get the response: “Type ‘svn help’ for usage.” You’re ready to go.

I’m a little rusty on Windows right now, but Linux users should be able to use the above steps with little modification.

Creating a Test Repository

This will be practice for the real thing. We’re going to create the repository in our home directory this time, just for the sake of simplicity. To do this we use the svnadmin command. At the prompt in your home directory (cd ~), type:

svnadmin create testrepo

You’ve just created a repository called testrepo. This currently exists as a database. Let’s add some files to the database.

mkdir test
touch test/test1.txt
touch test/test2.txt

SVN doesn’t have any idea these files exist yet, so let’s go ahead and make this directory part of the repository.

svn import test file:///Users/youruser/testrepo/test -m "Initial Import"

This will add a repository called test that we will be able to check out by name (well, by path) in a moment. You should see:

Adding         test/test2.txt
Adding         test/test1.txt

Committed revision 1.	

The “revision” is going to increment by a full step every time we commit a change to the repository. The -m parameter that we included in the import command added a message to the log defining what changed, and should be included with every commit that you make to the repository. A commit, which we will cover shortly, is a way of updating the repository with current changes and is something that is good practice to do often. And trust me, after 100 commits, remembering what number 27 was for will be a lot easier with a message like “removed styling from the microphones next to blog posts on front page”.

Check it Out

Okay, now we’re going to leave the original test directory alone. It’s going to stay “pristine” while we check out a working copy of the repository to make changes to. Type:

svn checkout file:///Users/youruser/testrepo/test workingtest	

You should see a list of all the files that are checked out and put into your working copy, which is now under revision control:

A    workingtest/test2.txt
A    workingtest/test1.txt
Checked out revision 1.	

cd to the working copy (cd workingtest) and type “ls -a”. You should see a hidden directory called “.svn”. This indicates that the current directory is under revision control and contains information about the directory and changes made to it. If you want a clean copy of the directory without the .svn directory, you’ll need to use the “svn export […]” command. But for our purposes, we’ll be setting up Apache to run off of a working copy and disallow descent into the svn folders. This will allow the repository to automatically update the testing or even live server when we commit changes from another working copy. We’ll get into the possible workflows in a later post. For now, let’s make some changes to our testing checkout.

Testing your Commitment

Open up test1.txt in a text editor and add some text to it. Not much, just enough to change the file. Save it and return to the command line. Type:

svn status

and you should see:

M	test1.txt

Now we need to “commit” the change to the repository. As I mentioned before, it’s good practice to do this with every change you make. I sometimes make a series of related changes before doing a commit, as long as they all are affecting the same part of my website and are usually dependent on each other. Not doing this defeats the purpose of revision control and will leave you with an incomplete log of changes, forcing you to revert more changes than necessary if something goes wrong. In a later post, we’ll look at how to test changes before committing them, but it won’t reduce the need for frequent commits. Anyway, commit by typing:

svn commit -m "Added text to text1.txt"	

This should output:

Sending        test1.txt
Transmitting file data .
Committed revision 2.	

Versions, Versions

To start seeing where all of this is taking us, type:

svn update

Which will output:

At revision 2.

Normally this command would be used to update a working copy with changes made in other working copies that had been commited, bringing it up to the latest revision. In this case, we’re in the only working copy so we’re already up-to-date. So it just tells us our current revision number. You can get a log of revisions by typing:

svn log

And see something like:

$ svn log
------------------------------------------------------------------------
r2 | brett | 2007-04-12 08:07:59 -0500 (Thu, 12 Apr 2007) | 1 line

Added text to text1.txt
------------------------------------------------------------------------
r1 | brett | 2007-04-12 07:56:53 -0500 (Thu, 12 Apr 2007) | 1 line

Initial Import
------------------------------------------------------------------------

To drill down to a little more detail we can use the svn diff command, which works very much like the diff command you may be used to. Try typing “svn diff -r 1” to compare your current working copy to revision 1.

Revision Rescue

There are 2 ways to rescue yourself from your own changes. Prior to a commit you can use “svn revert filename” to revert the working copies changes to the current committed revision. If you’ve already committed the changes and you’ve figured out what revision you would like to jump back to (using svn log or and/or svn diff), you can type “svn update -r x” where x is the revision number you’d like to revert to. Both of these commands can be used with and without specific filenames, where revert or update would act on the entire working copy or just the directory/filename you specify.

Telling SVN What’s Up

SVN doesn’t know about your changes unless you tell it. When you’re in a working copy, you need to explicitly tell svn to add, remove, move or rename files. The “svn help” command lists the commands you need to know in order to accomplish these tasks:

Available subcommands:
   add
   blame (praise, annotate, ann)
   cat
   checkout (co)
   cleanup
   commit (ci)
   copy (cp)
   delete (del, remove, rm)
   diff (di)
   export
   help (?, h)
   import
   info
   list (ls)
   lock
   log
   merge
   mkdir
   move (mv, rename, ren)
   propdel (pdel, pd)
   propedit (pedit, pe)
   propget (pget, pg)
   proplist (plist, pl)
   propset (pset, ps)
   resolved
   revert
   status (stat, st)
   switch (sw)
   unlock
   update (up)

In parenthesis next to each command is it’s shortcut or synonym. Important to note are “add”, “copy”, “move” and “delete”. These are the basic file management tools. Usage is just “svn [add,copy,move,delete] [filename]”. For more detail on a command, type “svn help (command)”.

After you run one of the above commands you’ll want to commit your change. For example, to add a file we create:

$ touch test3.txt
$ svn add test3.txt
A         test3.txt
$ svn commit -m "Added a file"
Adding         test3.txt
Transmitting file data .
Committed revision 3.

And to remove the file:

$ svn del test3.txt
D         test3.txt
$ svn commit -m "deleted a file"
Deleting       test3.txt

Committed revision 4.

You can check for changes that svn recognizes but doesn’t understand by typing “svn status”. Items that show up with a question mark are files it cannot account for, ‘M’ means the file has been modified, ‘D’ means deleted, ‘A’ means added… Question mark files will be ignored during a commit, so if they need to be handled, you’ll want to use the ‘add’ or ‘delete’ commands to take care of them. If they’re not part of the main project but you need them on your working copy, then they need to be ignored to remove the cruft from your svn output. This gets a little trickier.

Ignoring files

You can be careful not to import certain files to begin with. As you add files, you can choose to ignore them using the propset command I’ll get to in a second. However, when you’re working with something like a dynamic website, you’ll probably end up importing config and cache files that will either change themselves or need to be changed locally to work with a testing server instead of the production server.

You can set a property on a directory to tell svn to ignore files, but it won’t take effect while those files are under revision control. So if you’ve changed checked out files in your working copy that you don’t want checked back in, here’s the solution I worked out. If there’s a better way, I’d love to hear it.

First, you need to create a text file called “ignorefile” with each file or pattern to be ignored on a new line. Save the file. Then, in the directory containing the files or subdirectories to be ignored, run the command:

svn propset svn:ignore -F ignorefile .

This won’t have any immediate effect. Now copy the files out of the working copy into a safe location, or tarball them temporarily. Run “svn del” on the files to be ignored and commit the change. If you receive an error message when you commit, try “svn update” and then commit again. This will delete the files. Now when you copy them back in, they should be ignored, and typing “svn status” should not report them.

Here’s the catch. If you’ve checked out your whole website and have working copies on both sides, and then removed the configuration file in the root directory from svn control, you’ll need to do the copy and replace trick on both ends. When you commit the deletion of the file and then update your other working copy, it will delete the file there as well. You won’t want to replace it with your local copy, so you need to make sure you back up the file before you update. This takes some manual labor and is best done one step at a time so you can keep track of all the changes.

Up next

We’re going to actually check out a website and set up a local testing server next. We’ll detail a couple of possible workflows and put the commands we covered today to use. Then we’ll look into working in groups using Subversion. Finally, we’ll look at some graphical clients, the TextMate Subversion bundle, and of course, some alternatives to svn.

Reference:
Subversion with Mac OS X
The SVN Book

» » » » »
  1. Michael 04.12.07 / 1pm

    I genuinely appreciate you taking time to document this. I’ve wanted to take this approach for some time, and got as far as installing subversion, but got lost on this first step of creating the bash profile. Something that looks so simple completely tripped me up.

    If you are ever in the Tampa area, be sure to let me know, I’ll owe you a few beers after this tutorial series.

  2. Michael 04.12.07 / 1pm

    And as soon as I say “looks easy”, I realize I don’t know where to look/add the profile in the first place. Any hints?

  3. Brett Terpstra 04.12.07 / 2pm

    Yes. In your home directory, which is where your terminal should start out when you open it. To make sure, just type “cd ~”. That’s a tilde from the upper left hand corner of the keyboard ;). Doing an “ls .bash-profile” will show you if the file exists or not.

    To make things simple you can just type “pico ~/.bash-profile”, replacing pico with vi or mate or whatever editor you prefer to use.

  4. Brett Terpstra 04.12.07 / 2pm

    sorry, those should all be underscores… ~/.bash_profile.

  5. Michael 04.12.07 / 3pm

    cool, thanks, that’s what I did wrong, used the dash, not the underscore. Installing and restarting after that and it’s up and running, now to follow along.

  6. brett 04.12.07 / 3pm

    Oops, I forgot to add how to run the profile once it’s edited without logging out. I’ll stick that in right now.

  7. Circle Six Blog » Blog Archive » Working with Subversion 04.13.07 / 6pm

    […] so we’ve installed subversion and covered the basics. Let’s go ahead and make our first actual repository on a remote server and check out a local […]

  8. Ollie 06.26.07 / 8am

    Thank you for this great intro to Subversion.

    Wanted to let you know I did encounter one tiny typo:

    “svn —version”

    should be:

    “svn —version”

    I guess your Markdown or whatever converted it.

  9. Ollie 06.26.07 / 8am

    Seems it does the same in comments :)

    Let’s try that again with a code tag:

    svn --version

  10. brett 06.26.07 / 9am

    Fixed it. I just added a typography plugin since writing the post and I think it’s probably messed up a few of my old code posts. Thanks for catching it.

Have your say

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>




Safari hates me