I prefer git, but have been spending a lot with subversion working on Module::Build. To give myself local version control when offline (I was on an airplane), I layered a local git repository on top of the subversion checkout. (Yes, there might be better ways to do this with “git svn” but not as easily once already offline!)
Once I had taught git to ignore .svn directories and taught svn to ignore .git and .gitignore, I imported the whole project to git and proceeded with my normal workflow, creating separate branches for different things I was working on.
Once I was back online, I wanted to merge my work back to the subversion tree, while still preserving the commit history from when I was offline. A short bit of Perl programming later and I was done. For each of the git branches I had created, I generated a series of patch emails with “git format-patch”. Then, after having subversion revert all files back to the latest commit, I passed the patches on the command line to this program:
#!/usr/bin/env perl use 5.010; use strict; use warnings; use Email::Simple; use Path::Class; use File::Temp; die "$0: This is not an svn repo\n" unless -d '.svn'; for my $f (sort @ARGV) { say "*** $f ***"; # try to apply patch system("patch -p1 < $f"); die "Patch failed! Aborting!\n" if $?; # extract commit info my $email = Email::Simple->new( scalar file($f)->slurp ); my $subject = $email->header("Subject"); $subject =~ s{^\[PATCH[^\]]*\]\s+}{}; my $body = $email->body; $body =~ s{\A(.*?)---.*$}{$1}ms; # write commit info to tempfile and commit it my $temp = File::Temp->new; say {$temp} $subject; print {$temp} "\n$body" if $body; system("svn commit -F $temp"); die "Commit failed! Aborting!\n" if $?; }
I wouldn’t want this kind of hybrid VCS to be part of my regular workflow, but in a pinch when I wanted offline version control, it worked remarkably well.