You’re probably working too hard. Do any of these sound familiar?

An entire file shows up in your diff, you think it’s because someone changed the tabbing from 4 spaces to 2 spaces, but you aren’t sure so now you’re pouring over all the code.

Your co-worker decided to rearrange all of the methods in awesome.rb, but you didn’t notice they also changed the parameter order on one of the methods.

There are a pile of small changes in large methods, and your diff didn’t show you what the method names were.

You have no idea what you have been working on for the last 2 hours, and can’t remember what to put in your check in message.

If they don’t, then humor me and pretend that they do, because I’m trying to motivate this tool I just wrote and I want you to be interested. What you secretly have been wanting is not a textual diff, but a logical diff, and that’s exactly what RubyDiff does (neat!). So grab it now:

sudo gem install ruby_diff

RubyDiff scans over your code and builds a logical model which it can use to tell you the really important high level information you need. Lets take a look at two versions of my enterprise pancake code:

Sample Version 1

module Food class Pancake def is_yummy? true end def << ingredient puts "adding #{ingredient}" end def self.build(ingredients) p = Pancake.new ingredients.each{|i| p << i} p end end end

Sample Version 2

module Food class Pancake def << ingredient (@ingredients ||= []) << ingredient end def self.about puts "A delicious morning treat" end def is_yummy? true end end class PancakeFactory class << self def build(ingredients) p = Pancake.new ingredients.each{|i| p << i} p end end end end

Now, the important thing here is not that waffles are better, but that a bunch of things have changed, and the question is… what was it?

ruby_diff test_a.rb test_b.rb c Food c Food::Pancake - Food::Pancake.build c Food::Pancake#<< + Food::Pancake.about + Food::PancakeFactory

RubyDiff shows us that the module Food has changed, within it the Pancake class changed. The class method Pancake.build was removed and a new PancakeFactory class was added. We also see that the append operator was modified and there is a new class method about. Great!

Best of all you can run ruby_diff over an entire repository of code, and it even supports git. For instance to see what changes you have made locally you can do something like:

ruby_diff --git HEAD --file ./ (your amazing changes here)

Or just to be meta, compare two revisions of RubyDiff:

ruby_diff --git HEAD~4 --git HEAD~3 c CodeChange c CodeChange#initialize c CodeChange#to_s c CodeComparison c CodeComparison#changed c CodeObject + CodeObject#child_signatures c StructureProcessor c StructureProcessor#diff

I’ll post more about RubyDiff shortly, but the source is available now on rubyforge and you can branch it on github. It’s still in it’s early stages, so I’d love to hear what you think.