Mastering the art of command line jujitsu is something every developer (regardless of OS) should strive for. While OS UIs are becoming more and more slick and helpful tools are abundant, possessing the ability to drop into a console and efficiently knock something out (find . -iname *.java | xargs egrep -i “todo” anyone?) has come in handy, for me at least, on more than one occasion.

For instance, every modern IDE now has a plug-in that facilitates working with Subversion– in fact, when I made the switch to Subversion from CVS a fews years back, I initially failed to even learn the Subversion commands– my favorite tools did it all for me graphically! Yet, in some cases I found myself distrusting the implementations these tools provided– for instance, one of my favorite CVS commands was cvs -nq update, which effectively tells you what’s changed in your local sandbox as compared to the tip of the CVS repository. This, of course, is handy in figuring out what you plan on committing; hence, I would run this command before a cvs commit so as to filter out unneeded changes.

This developmental cadence of making changes and checking them against the tip (and consequently committing them) is actually common among SCM systems– the cadence has three steps:

  • updating a local sandbox to reflect what is in a repository
  • understanding what has changed locally
  • committing local changes into a repository

With Subversion, these three steps can be achieved via the command line with three commands:

The svn update command takes any changes in a Subversion repository and pushes down to a local sandbox. For instance, if more than one person is making changes and committing those changes into a repository, when another person runs the svn update command, those changes will be literally downloaded into that person’s sandbox.

Using the update command is as easy as opening up a console and typing:

tty:~/dev/projects/easyb/ yts$ svn update

If there are changes in the repository, you should see some scrolling text like so:

U    maven-plugins/maven-easyb-plugin/src/main/java/org/easyb/maven/StoryReportMojo.java
U    maven-plugins/maven-easyb-plugin/src/site/apt/usage.apt
U    maven-plugins/maven-easyb-plugin/src/it/story-report-location-test/pom.xml
U    maven-plugins/maven-easyb-plugin/src/it/site-examples-test/pom.xml
U    intellij-plugins/easyb-plugin/easyb-plugin.iws
U    intellij-plugins/easyb-plugin/src/main/java/org/easyb/plugin/ui/EasybPresenter.java
U    intellij-plugins/easyb-plugin/pom.xml
Updated to revision 329.

Note, the U means updated– there are other characters for new files added, merged, in conflict, etc. What’s key here is that by running the update command, your local sandbox is in sync with what’s on the server. Running this command often often means you’ll probably avoid conflicts too!

After you’ve made some local changes, it’s often times helpful to capture what those changes were– if you’ve been working for any length of time or working with more than one file, you’ll most likely find the diff command indispensable.

Like the update command, diff can be run via the command line like so:

tty:~/dev/projects/easyb/ yts$ svn diff

This command will compare what’s in the repository with what’s in a local sandbox; what’s more, it’ll report on the exact changes as follows:

Index: behavior/groovy/org/disco/bdd/prototype/FixtureFeature.story
===================================================================
--- behavior/groovy/org/disco/bdd/prototype/FixtureFeature.story        (revision 322)
+++ behavior/groovy/org/disco/bdd/prototype/FixtureFeature.story        (working copy)
@@ -4,7 +4,7 @@
 description "this story is fleshing out fixture logic for scenarios"

-each "some description" , {
+every "some description" , {
     given "a value", {
         value = 12
     }
Index: src/groovy/org/disco/easyb/StoryBinding.groovy
===================================================================
--- src/groovy/org/disco/easyb/StoryBinding.groovy      (revision 322)
+++ src/groovy/org/disco/easyb/StoryBinding.groovy      (working copy)
@@ -102,7 +102,7 @@
       listener.describeStep(description)
     }

-    binding.each = {  description = "", closure = {} ->
+    binding.every = {  description = "", closure = {} ->
         beforeScenario = closure
     }
     return binding

As you can see in the text above, the local code (labeled as “working copy”) has changed the each call with every, which appears in revision 322 of the repository.

Once you’ve reviewed these changes and are happy with what you’ve got, you can then proceed to push these changes into the repository via the svn commit command– of course, this assumes you’ve run a local build and it passed successfully, right?

tty:~/dev/projects/easyb/ yts$ svn commit -m "updated dsl to use every instead of each"

Note that the commit command can take a flag (-m) that enables you to specify a comment. You should see some text indicating the changes are being pushed into the repository.

Sending        easyb/behavior/groovy/org/disco/bdd/prototype/FixtureFeature.story
Sending        easyb/src/groovy/org/disco/easyb/StoryBinding.groovy
Transmitting file data ..
Committed revision 325.

Note how these changes increment the revision number in Subversion– this is key as all commands allow you to work with various revisions (via flags); hence, by knowing a particular revision, you can logically branch if needed.

These three Subversion commands will come in handy if you aren’t already using them; hence, learn them now! Indeed, for becoming one with the command line is the path to enlightenment.