Josh Susser's blog



Josh SusserJosh Susser
svn to git protips
edit Posted by Josh Susser on Wednesday September 30, 2009 at 11:20AM

When you're moving a codebase from subversion to git, here are a few things that make the move go a bit more smoothly.

In the svn project, you can discover some things you'll need to adjust in git after the import.

Show all files being ignored

svn propget -R svn:ignore .

Add these files to the .gitignore file at your project root, or in appropriate subdirectories. I prefer keeping it all in one place at the top level.

Show all externals

svn propget -R svn:externals .

You'll either have to switch to using a submodule in git, or just pull the files into your project if that's not possible for some reason.

Find all empty directories

find . -type d -empty
touch /path/to/empty/dir/.gitkeep

Since git doesn't keep empty directories, you can add a .gitkeep file to empty directories that you don't want to go away. Some people add a .gitignore file to keep the directory around, but that sounds totally backwards to me. You want to keep it, not ignore it.

By the way, if you are already ignoring dir/*, that will ignore the .gitkeep file as well. Make sure it isn't missed by adding !.gitkeep to the end of your .gitignore file.

Find all authors

If you want to properly attribute commits, you'll need to set up an authors file. But if you miss any authors, the clone will stop and complain. You can discover all the svn users that you need to put in the authors file with this command:

svn log | grep -E 'r[0-9]+ ' | cut -d\  -f3 | sort | uniq

init + fetch > clone

If git svn clone doesn't complete, try doing the init/fetch as separate operations. The clone subcommand is pretty much just doing an init followed by a fetch, but I've found that if the clone fails, doing the commands separately can have better success.

Josh SusserJosh Susser
Simple DRY Validations
edit Posted by Josh Susser on Monday September 14, 2009 at 09:30AM

Here's a handy trick for making custom validations easily reusable.

This is an extract from a customer model with three different street addresses, in which we validate all three of the zip codes. (In this code, the GeoState.valid_zip_code? method answers if something that looks like a zip code is an actual zip code - not all five digit combinations are in use as zip codes, and we want to make sure we've got a live one.)

def validate_home_zip_code
  validate_zip_code(:home_zip_code)
end

def validate_mailing_zip_code
  validate_zip_code(:mailing_zip_code)
end

def validate_previous_zip_code
  validate_zip_code(:previous_zip_code)
end

def validate_zip_code(field)
  errors.add(field, :inclusion) if errors.on(field).nil? && !GeoState.valid_zip_code?(send(field))
end

validates_presence_of :home_zip_code
validates_format_of :home_zip_code, :with => /^\d{5}(-\d{4})?$/, :allow_blank => true
validate :validate_home_zip_code

validates_presence_of :mailing_zip_code
validates_format_of :mailing_zip_code, :with => /^\d{5}(-\d{4})?$/, :allow_blank => true
validate :validate_mailing_zip_code

validates_presence_of :previous_zip_code
validates_format_of :previous_zip_code, :with => /^\d{5}(-\d{4})?$/, :allow_blank => true
validate :validate_previous_zip_code

That looks very wet to me. (WET == "Write Every Time") But it's not too hard to dry this up using just a tiny bit of knowledge of how ActiveRecord validations work.