“Undoing” an SVN revision

This is the second in a series of posts I began this summer and didn’t have time to finish.

Edit 2011/01/17: I finally noticed and fixed a small glitch in the raw command line I was using, probably caused by my use of “<>” in the example text. Sorry, folks.

We all know how it feels, right? You’ve been coding away happily, decide it’s time to push everything to your version control system of choice, type out a brilliant commit message, and hit Enter–only to find out five seconds later that you just committed something you shouldn’t have committed and everyone else is in trouble when they happen to update. What do you do now?

Well, if you have a decent version control system (VCS) such as Mercurial or Git, you take advantage of the built-in undo or undo-like command and simply undo your commit. Most modern distributed VCS’s have one, giving you at least one chance to fix your work before you hand it out for everyone else to use. However, some less-than-fun VCS’s make it difficult (mostly because they’re designed to keep the information you give them forever, warts and all, which is not a bad thing). However, it’s still usually possible to fake an undo.

Take Subversion, for example. It’s not my favorite VCS for reasons I may go into later, but it’s still a very solid one if you like and/or need the centralized type of thing. I used it a lot this summer while doing an internship with Sentry Data Systems, and I found myself needing to rollback a commit on some files a time or two. So, I did some research.

Graphical representation of a merge

Arguably the best way to rollback a commit in Subversion is to perform what they call a reverse-merge. In a normal merge, you take two versions of a file, compare them to figure out what’s different between them, and then create a new file containing the consensus content of both files (see picture to the right).

Graphical representation of a reverse merge

In a reverse-merge, you figure out what changes were made in a given revision, and then commit a new revision that reverts all of those changes back to the version before you committed your bad revision (see picture to the right), which means your bad revision will be simply skipped over as far as your comrades are concerned. Subversion provides a simple series of commands for this:

svn merge -c -{bad revision number} [{files to revert}]

Here’s how it works.

  1. The svn merge portion of the command basically tells Subversion you want to merge something. svn is the command-line tool to interact with a Subversion repository, and merge…well, you get the idea.
  2. -c -{bad revision number} tells Subversion that we want to work with the changes related to the revision numbered {bad revision number}. In this case, since we’re passing in a negative sign in front, we’re saying we want to remove those changes from the working directory. If you left out that negative sign, you’d actually pull the changes from that revision into the current working directory, which is usually only useful if you’re cherry-picking across branches. Whether that’s a good idea or not is left to the reader.
  3. [{files to revert}] are an optional list of files to undo changes in. Basically, if you pass in a list of files here, only those files will have their changes from revision–any other files changed in that revision will not be affected.

That’s pretty much it. Once you run that command (assuming there are no conflicts in your merge), you will be able to simply commit (with a helpful commit message, of course) and everything will be back to normal–your comrades in arms will be able to keep working without the overhead of your bad commit cluttering up their working environment, which is always a good thing.

Tar Pipe

This is the first in a series of posts I began this summer and only now have time to finish.

Every once in a while, I find myself needing to copy a large number of files from one Linux machine to another, ideally as fast as possible.  There are a lot of ways to do this, but the most common method usually goes something like this:

  • Tar everything up (with some form of compression if your network connection is slow).
  • (S)FTP/SCP  the file to the new server.
  • Move the file to the new location, making directories as needed.
  • Extract the tar file into the new directory.

This is all well and good, and it tends to work well in most cases–it’s just kind of laborious.  I prefer a simpler method that basically wraps everything up into a single step, affectionately known as a tar pipe.  The (admittedly somewhat complex) command follows.

  SRCDIR=  # fill in with your source directory
  DESTDIR= # fill in with your destination directory--note that your
           # uploaded directory will appear inside this one
  USER=    # fill in the your remote user name
  HOST=    # fill in with your remote host name
  tar -cvzf - $SRCDIR | ssh $USER@$HOST "mkdir -p $DESTDIR; tar -xz -C $DESTDIR

The variables are just to make things a little more easy to read (feel free to ignore them if you like), and I do recommend using a full path for the DESTDIR directory, but the basic process is ridiculously easy.  Here’s the breakdown on how the whole thing works.

  1. The tar -cvzf - $SRCDIR very obviously tars everything up, just like you normally would.  The key difference from the normal tar procedure is the fact that the “file” you’re creating with tar is actually sent to stdout (by the -f - option) instead of being written to the file system.  We’ll see why later.
  2. The | (pipe) passes everything on stdout on as stdin for the next command, just like normal.
  3. The ssh command is the fun part.
    1. We start an ssh session with $HOST as $USER.
    2. Once that’s established, we run two commands.
      1. mkdir -p $DESTDIR to make the destination directory, if needed.
      2. tar -xz -C $DESTDIR to untar something. What, we’re not sure yet.

What it untars is a bit of a mystery, as we don’t really tell it what it’s supposed to work on.  Or do we?  As it turns out, ssh passes whatever it receives on stdin on to the command it runs on the server.  I.e., all that stuff we just tar’red up gets passed along through the magic of piping from the local machine to the remote machine, then extracted on the fly once it gets to that machine.

You can see the benefit of this, I trust–instead of that whole four command process we detailed above, including manually logging into the remote server to actually extract the new file, we have one fairly simple command that handles taring, uploading, and extracting for us, with the added benefit of not requiring us to actually create any files we don’t have to create.  That’s kind of cool, right?

Note:  I’ve seen other implementations of the tar pipe, but this is the one I’ve used been using recently.  It’s worked for me on Red Hat 5, but your mileage may vary.

Résumé

CHAD BURRUS


113 N. Meridian St., Washington, Indiana 47501 (812) 783-9127;
[email protected]

Experience

Sentry Data Systems—Deerfield Beach, Florida
Software Developer: May 2011-Present

  • Served on an engineering board to address developer culture, standardize coding practices among
    projects and teams, and lead high-level software engineering decisions.

  • Managed our Jenkins server, including adding and updating builds as well as system-level
    configuration.

  • Managed releases of our SaaS products including actual rollouts with Capistrano and scripted database
    updates to Oracle.

  • Co-led a project to convert our Subversion repository to git.

  • Updated our Symfony 2.0 applications to use Symfony 2.1.

  • Integrated a Salesforce portal for customer support and help desk utilization.

  • Developed internal tools with PHP, PL/SQL, Ruby, and Twig.

School of Informatics and Computing, Indiana University—Bloomington, Indiana
Research Assistant: Jan. 2010-May 2011

  • Explored new association methods to compare metagenomic samples based on environmental data.

  • Wrote Python, R, and C++ code to analyze the differences in metagenomic samples including statistical
    tests and graph construction and development.

Sentry Data Systems—Deerfield Beach, Florida
Developer Intern: May 2010-Aug. 2010

  • Use PHP, PHPUnit, and PL/SQL to develop internal tools, including wrapping a set of PL/SQL classes
    with easy-to-use PHP classes.

  • Configure a Hudson build to ensure products stayed in good working order.

School of Informatics and Computing, Indiana University—Bloomington, Indiana
Associate Instructor, I101: Sept. 2009–Dec. 2009

  • Taught and graded weekly labs.

  • Assisted teaching additional lab sessions.

Cognitive Solutions, LLC.—Clearwater, Florida
System Developer: Sept. 2008–Aug. 2009

  • Developed both front-end and back-end components and features for a toy-tracking web application as
    part of a distributed development team.

LAT, Inc.—Marion, Indiana
Developer: Jan.–June 2006
Architect: June 2006–Aug. 2008

  • Designed and developed both front-end and back-end components and features for a wide range of web
    applications.

  • Served as technical lead for several projects, as well as occasional technical support and system
    administrator.

Education

Indiana University—Bloomington, Indiana
MS in Bioinformatics

  • Graduated May 2011 with an overall GPA of 3.95

Indiana Wesleyan University—Marion, Indiana
BS in Computer Science, Minor in Mathematics

  • Graduated April 2005 with an overall GPA of 3.75

Skills

Operating Systems:

  • Proficient with Linux (Ubuntu, Red Hat), Mac OS X, Windows 98/ME/XP/Vista/7

Computer Languages:

  • Proficient with CSS, HTML, Java, Javascript (including AJAX), LATEX, PHP, Python, XML, XSLT

  • Familiar with Ada, C, C++, Cobol, Matlab, Octave, Perl, R, Ruby, SQL (MySQL, PL/SQL, PostgreSQL,
    and SQL Server flavors)

Tools and Systems:

  • Proficient with Bash, CVS, git, jQuery, Komodo Edit, Mercurial, MySQL, Microsoft SQL Server,
    MooTools, PHPUnit, Scite, Subversion, Symfony 2, Twig, VIM

  • Familiar with Apache HTTP Server, Capistrano, Doctrine, Eclipse, Graphviz, Hudson/Jenkins, Joomla,
    Oracle

Achievements and Activities

ACM:

  • Student Member, 2003-2005.

  • Professional Member, 2005-Present.

IEEE Computer Society:

  • Student Member, 2005.

  • Associate Member, 2006-2009.

  • Graduate Student Member, 2009-2011.

  • Associate Member, 2011-Present.

Awarded Eagle Scout Rank, Boy Scouts of America (2000).

References

Available on request.