VSS to SVN: Part 3 2

Posted by jeff Friday, June 22, 2007 14:51:00 GMT

Now that you have the Subversion client installed, let's get down to business. These examples use the command-line client, but those of you who installed TortoiseSVN should be able to follow along, too.

Checking Out

There's a subversion repository already setup somewhere, and you want to get some code out of it. To do that, use the "checkout" command. Remember, fellow VSS alumni, Subversion "checkout" is a totally different animal from a VSS "checkout". Subversion checkout means "this is the first time I'm getting this source code project from the repository."

What repository should we use? Let's use the publicly available "trunk" branch from Rails itself. We won't be able to commit our changes, since only core team members have that kind of permission enabled, but we can do almost everything else. Also, I prefer to use the short form of some of the svn commands, and "co" is the short form of "checkout":


c:\dev> svn co http://svn.rubyonrails.org/rails/trunk
This will place the code into `c:\dev\trunk`. If we had specified an optional path parameter, we could have put it anywhere we wanted; by default, it uses the right-most part of the svn path as the name of a new subfolder it should create on your machine. The Rails project contains *a lot* of code, so this will take a minute or two. Once it's done, take a look!
c:\dev> cd trunk
c:\dev\trunk> dir
Those directory names should be familiar. But before we do anything else, let's learn about the "status" command, which can be abbreviated "st":
c:\dev\trunk> svn st
And nothing should appear. That's good! That means that since our checkout, we haven't added, deleted, or changed any of the source files. By the way... how did it *know* that we hadn't done any of those things? When we did the checkout, Subversion not only got the latest code from the repository, it also created a hidden directory alongside the code called `.svn`, into which it placed a number of things, including a full copy of everything we just got. This means it can quickly know if we've changed anything locally by comparing against it's last-known copy of what the repository looked like when we did the checkout. This hidden copy is often called the BASE version, as opposed to HEAD, which is the real live latest version that's in the real repository. So after we checkout a project, HEAD can change a lot if other developers on the team are checking in their code; but BASE will remain the same. (We'll find out how to update our BASE copy in a minute.)

Edit Some Code

For now, let's dive down into one of the ActiveRecord source files:
c:\dev\trunk> cd activerecord\lib\active_record
and let's edit the `callback.rb` file. Open it up in your favorite editor, and the top part should look like this:

    require 'observer'

    module ActiveRecord
      # Callbacks are hooks into the lifecycle of an Active Record object that allows you to trigger logic
      # before or after an alteration of the object state. This can be used to make
Put your cursor on the blank line between the 'require' and 'module' statements, and enter some code, maybe something like this:

    require 'observer'

    module OldSourceControl
       def goodbye_vss
          # send an email to the vss administrator
          # announcing the new Subversion repository in the office.
       end
    end

    module ActiveRecord
Or whatever... you get the idea. In real life, you would be changing some real code for some real project you're working on. Save that file and get back to the command line. Let's get back to our root directory and do another "status" command:

    /dev/trunk$ svn st
    M      activerecord/lib/active_record/callbacks.rb
    /dev/trunk$
The status command lists all file changes (adds, modifications, deletes, etc.) in a two-column format (well, there's actually three, but we're not going to worry about that right now). The first column is an indicator of the kind of change it has detected. Here it's an "M", meaning that the file is already under source control but it has local modifications. If you ever see a file with a "?" indicator, the file isn't under source control yet; you'll need to perform an `add` command to get Subversion to track changes to it.

Diff

Modern tools like TortoiseSVN and TextMate have nice views for this, but you can even do it at the command line:

    ~/dev/sandbox/rails/trunk> svn diff activerecord/lib/active_record/callbacks.rb 
    Index: activerecord/lib/active_record/callbacks.rb
    ===================================================================
    --- activerecord/lib/active_record/callbacks.rb (revision 7073)
    +++ activerecord/lib/active_record/callbacks.rb (working copy)
    @@ -1,5 +1,12 @@
     require 'observer'

    +module OldSourceControl
    +  def goodbye_vss
    +    # send an email to the vss administrator
    +    # announcing the new Subversion repository in the office.
    +  end
    +end
    +
     module ActiveRecord
       # Callbacks are hooks into the lifecycle of an Active Record object that allows you to trigger logic
       # before or after an alteration of the object state. This can be used to make sure that associated and

A discussion of the standard diff format is beyond this article, but here are the highlights to break the ice:
Index: activerecord/lib/active_record/callbacks.rb
===================================================================

This shows up for each file we're diff'ing. In our case we're only diffing one file, but you can run svn diff against a directory instead.

--- activerecord/lib/active_record/callbacks.rb (revision 7073)
+++ activerecord/lib/active_record/callbacks.rb (working copy)

This declares the legend for what follows. The "-" signs will represent code coming from the "revisiion 7073" version (that was the version that we got from the checkout command), while the "+" signs will represent code from our local working copy.

Skip down to the code, and you'll see a lot of lines prefixed with "+" signs; that's code that we added. There isn't any code with "-" prefixes, because we didn't delete any of the original code.

There are some lines without either prefix - that's because the diff will give you some "context" around each change, so you can get your bearings on what part of the code you're looking at.

Update

Before we commit our changes, and unless you're the only developer on the project, you'll want to first update your local code from the repository. Unlike the default VSS environment, it's possible that someone else committed changes to a file that you've been working on locally.

Anytime you want to "get latest" from Subversion, run the "update" command:

/dev/trunk$ svn update

You'll see output similar to the output from the status command: 'A' will mean a file was added, etc. But there are two new status indicators you need to be aware of:

  • G means that the file on the host was modified, but Subversion was able to successfully merge those changes into your local copy (this is what usually happens).
  • C means that the file on the host was modified, but for some reason you and your colleague both edited the same exact lines in the file (guess you don't like to talk to each other all that much). You'll have to edit the file manually and run svn resolved <path> before you try to commit the file.

Commit

Finally: commiting your changes back to the repository. This won't work on our Rails trunk, but I'll show you how the commit command would work for your own projects:

c:\dev\trunk> svn commit -m "My cool new module code"

Couple of important things to understand:

  • The -m parameter is required. This provides a description for your commit, so that others can find out why you made your changes.
  • Unlike VSS, the commit operation is an atomic transaction. All of the files you've changed will be checked in, but if any one of them fails for any reason, the transaction is rolled back.
  • The commit command will not automatically know to add any new files you've created locally to the repository. To do that, you need to first manually call the svn add command.

Leftovers

That's it for our whirlwind tour of Subversion. There are a many things I didn't cover, because once you understand the philosophy of Subversion (which I hope you do now), the other topics are simply a matter of looking them up in a real Subversion reference (like the ones I mentioned in part 1. Topics you should learn about that I'm not covering here are:

  • Importing projects (creating new projects from source you have locally)
  • Creating branches and tags
  • Viewing file history (hint, use the svn log command)

Remember, type svn help to get a list of commands, and svn help <command> to get learn about any command you're curious about. I'm also available to answer questions about anything I covered or didn't have time to cover - just leave a comment below.

And I hope you fellow VSS users out there can now feel a little more prepared to work with Subversion. My guess is, once you get a chance to spend a little time with it, you'll never go back.

Comments

Leave a response

  1. Dylan Bennett  June 23, 2007 @ 04:47 AM

    Can't say it enough. Great set of articles! Thank you very much for the time taken to write them.

  2. Scott Hodson  June 30, 2007 @ 07:03 AM

    Good job guys! As a .NET and Rails developer and user of RCS (long time ago), then VSS, then CVS and later Sourcegear Vault, it's refreshing to try to get people thinking only the VSS way and to work in a more concurrent manner, and SVN is such a nice upgrade from CVS, especially atomicity.

Comment