<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -94,9 +94,7 @@ Checking out older commits is extremely easy to do.
   @page.checkout(:previous)       # Previous commit
   
   @page.checkout(:root)           # Base commit for branch
-  
-  @page.checkout('^^')            # 2 commits ago
-  
+    
   @page.checkout(6)               # 6 commits ago
   
   @page.checkout(&quot;tag:final-2&quot;)   # Revision tagged 'final-2'</diff>
      <filename>README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,3 @@
-$:.unshift(File.dirname(__FILE__)) unless
-  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
-
 require 'digest'
 require 'activesupport' unless defined? ActiveSupport  
 require 'activerecord' unless defined? ActiveRecord
@@ -11,4 +8,5 @@ require 'revisionary/common'
 require 'revisionary/core'
 
 ActiveRecord::Base.send(:include, Revisionary::ActsAsScopedModel)
-ActiveRecord::Base.send(:include, Revisionary)
\ No newline at end of file
+ActiveRecord::Base.send(:include, Revisionary)
+ActiveRecord::Base.send(:include, Revisionary::Common)
\ No newline at end of file</diff>
      <filename>lib/revisionary.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,38 +0,0 @@
-module Revisionary
-  module Association
-    module ClassMethods
-      
-      def register_owner(owner, polymorphic_assoc = nil)
-        @revisionary_owner = owner
-        @revisionary_polymorphic = polymorphic_assoc
-      end
-      
-    end
-    
-    module InstanceMethods
-      
-      def set_owner(owner)
-        assoc = self.class.reflect_on_all_associations.find { |a| a.klass == owner.class } rescue nil
-        send(assoc ? &quot;#{assoc.name}=&quot; : &quot;#{self.class.revisionary_polymorphic}=&quot;, owner)
-      end
-      
-    end
-    
-    def self.included(receiver)
-      receiver.extend         ClassMethods
-      receiver.send :include, InstanceMethods
-      receiver.instance_eval do
-        
-        class &lt;&lt; receiver
-          
-          attr_accessor :revisionary_owner
-          attr_accessor :revisionary_polymorphic
-          
-        end
-        
-        before_update :clone
-        
-      end
-    end
-  end
-end
\ No newline at end of file</diff>
      <filename>lib/revisionary/association.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,7 @@ module Revisionary
   module ClassMethods
     
     def is_revisionary(options = {})
-      self.send(:include, Revisionary::Core)
+      self.send(:include, Revisionary::Core, Revisionary::Common)
       class &lt;&lt; self
         attr_accessor :revisionary_options
       end</diff>
      <filename>lib/revisionary/base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,53 +1,73 @@
 module Revisionary
   module Common
     
+    def self.included(receiver)
+      receiver.extend         ClassMethods
+      receiver.send :include, InstanceMethods
+    end
+    
     module ClassMethods
       
+      # columns to be skipped when creating comparison hashes
+      def skipped_columns
+        arr  = %w(source_hash object_hash original_commit_id commit_created_at commit_message commit_tag created_at updated_at) + [self.primary_key]
+        arr += self.ignored_columns if self.included_modules.include?(Revisionary::Core)
+        arr
+      end
+      
+      def ignored_columns
+        [self.revisionary_options[:ignore]].flatten.map(&amp;:to_s)
+      end
+      
+      # returns an array of monitored associations
       def associations
-        [self.revisionary_options[:with] || []].flatten
+        return [] unless self.included_modules.include?(Revisionary::Core)
+        [self.revisionary_options[:with]].flatten
       end
       
-      def skipped_revisionary_attributes
-        %w(source_hash object_hash object_created_at branch_id is_head commit_message commit_tag) + [self.primary_key]
+      def clone_column?(col)
+        not self.skipped_columns.include?(col)
       end
       
     end
     
     module InstanceMethods
       
-      # Generates unique hash for object and monitored associations
-      def commit_hash
-        hash = self.attributes.reject { |k, v| self.class.skipped_revisionary_attributes.include?(k.to_s) }.values.join(':')
-        array = associations(true).inject([]) do |arr, (key, assoc)|
-          as = self.send(key)
-          if as.is_a?(Array)
-            as.map { |o| o.attributes.reject { |k, v| [:id, :page_id].include?(k.to_sym ) }.values.join(':') }.join(':')
-          else
-            # TODO
-          end
+      def cloneable_attributes
+        attributes.dup.reject { |k, v| !self.class.clone_column?(k.to_s) }
+      end
+      
+      # generates a unique hash for object
+      def commit_hash(origin_class = nil)
+        @origin_class = origin_class
+        combined  = self.attributes.reject { |k, v| self.class.skipped_columns.push(self.get_origin_foreign_key).flatten.include?(k.to_s) }.values.join(':')
+        combined += self.class.associations.inject([]) do |arr, assoc_name|
+                      association = self.send(assoc_name)
+                      association.is_a?(Array) ? association.map { |a| a.commit_hash(self.class) } : association.commit_hash
+                    end.join(':')
+        #Digest::SHA1.hexdigest(combined)            
+      end
+      
+      # revert columns in object to previous state - requires Rails 2.1
+      def revert_columns(object)
+        self.class.column_names.each do |col|
+          next unless self.class.clone_column?(col)
+          value = self.send(&quot;#{col}_changed?&quot;) ? self.send(&quot;#{col}_was&quot;) : self.send(col)
+          object.send(&quot;#{col}=&quot;, value)
         end
-        Digest::SHA1.hexdigest([hash, array].flatten.join(':'))
       end
       
-      # returns monitored associations
-      def associations(load = false)
-        return [] unless self.class.included_modules.include?(Revisionary::Core)
-        self.class.apply_revisionary_to_associations
-        assoc = self.class.associations
-        if load
-          assoc = assoc.inject({}) do |hsh, as|
-            hsh[as] = send(as.to_sym)
-            hsh
+      protected
+      # this will not work with polymorphic associations
+        def get_origin_foreign_key
+          if @origin_class
+            return [@origin_class.revisionary_options[:polymorphic]].map { |p| [ &quot;#{p}_type&quot;, &quot;#{p}_id&quot; ] }.flatten
+            foreign_key = self.class.reflect_on_all_associations.find { |a| a.klass == @origin_class }.options[:foreign_key].to_s
+            @foreign_key ||= foreign_key.blank? ? [@origin_class.name.downcase + '_id'] : [foreign_key]
           end
         end
-        assoc
-      end
       
     end
     
-    def self.included(receiver)
-      receiver.extend         ClassMethods
-      receiver.send :include, InstanceMethods
-    end
   end
 end
\ No newline at end of file</diff>
      <filename>lib/revisionary/common.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,38 +1,48 @@
 module Revisionary
   module Core
     
-    module ClassMethods
+    def self.included(receiver)
+      receiver.extend         ClassMethods
+      receiver.send :include, InstanceMethods
       
-      def apply_revisionary_to_associations
-        self.associations.each do |assoc|
-          [Revisionary::Common, Revisionary::Association].each { |m| self.reflect_on_association(assoc).klass.send(:include, m) }
-          self.reflect_on_association(assoc).klass.send(:register_owner, self, self.reflect_on_association(assoc).options[:as])
-        end
+      class &lt;&lt; receiver
+        alias_method_chain :find, :commits
+        alias_method_chain :count, :commits
       end
       
-      def clone_column?(col)
-        self.skipped_revisionary_attributes.include?(col)
+      receiver.instance_eval do
+        
+        alias_method_chain :save, :commit
+        alias_method_chain :save!, :commit
+        
+        # this will ensure that we only ever find the actual object, not the commits
+        acts_as_scoped_model :find =&gt; { :conditions =&gt; { :original_commit_id =&gt; nil } }
+                
+        before_save :setup_commit
+        before_update :clone_previous
+        after_update :save_commit
+        
+        attr_accessor :revisionary_commit_tag
+        
       end
       
-      def find_by_branch(*args)
-        self.find_by_branch_id(args.first)
-      end
+    end
+    
+    module ClassMethods
       
       def find_with_commits(*args)
         options = args.grep(Hash).first
-        
         if options &amp;&amp; options.delete(:with_commits)
           without_model_scope do
             find_without_commits(*args)
           end
         else
-          find_without_commits(*args)
-        end  
+          find_without_commits(*args)          
+        end
       end
       
       def count_with_commits(*args)
         options = args.grep(Hash).first
-        
         if options &amp;&amp; options.delete(:with_commits)
           without_model_scope do
             count_without_commits(*args)
@@ -42,217 +52,149 @@ module Revisionary
         end
       end
       
-      def with_scope_with_commits(*args, &amp;block)
-        options = args.grep(Hash).first[:find]
-        
-        if options &amp;&amp; options.delete(:with_commits)
-          without_model_scope do
-            with_scope_without_commits(*args, &amp;block)
-          end
-        else
-          with_scope_without_commits(*args, &amp;block)
-        end
-      end
-      
-      
     end
     
     module InstanceMethods
       
-      # access the source object
-      def source_hash
-        read_attribute(:source_hash) || self.commit_hash
-      end
-      
-      # access the tag (if exists)
-      def tag
-        self.commit_tag
+      def commits(conditions = {})
+        scope, count = conditions.delete(:scope), conditions.delete(:count)
+        options = { :conditions =&gt; { :original_commit_id =&gt; self.id }.merge(conditions), :order =&gt; 'commit_created_at desc, id desc', :with_commits =&gt; true }
+        count ? self.class.count(options) : self.class.find(scope || :all, options)
       end
       
-      # check to see if current is tagged
-      def tagged?
-        not self.tag.nil?
+      def commits_count
+        commits(:count =&gt; true)
       end
       
-      # revert to another version, again, thanks to Rich of acts_as_revisable!
-      def revert_to!(pointer, options = {}) 
-        
-        begin       
+      def revert_to!(pointer, options = {})
+        begin
           revision =  case pointer
-                      when :previous, :last, '^'
-                        ancestry.first
+                      when :previous
+                        commits(:scope =&gt; :first)
                       when :root
-                        ancestry.last
-                      when '^^', '^2'
-                        ancestry[1]
-                      when /\^(\d+)/        # ^3, ^15, whatever.
-                        ancestry[$1.to_i]
+                        commits(:scope =&gt; :last)
                       when Fixnum
-                        ancestry[pointer-1]
+                        commits[pointer-1] || commits(:scope =&gt; :last)
                       when /tag:(.*)/
-                        ancestry.find { |a| !a.commit_tag.blank? &amp;&amp; a.commit_tag.downcase == $1.downcase }
+                        commits(:scope =&gt; :first, :commit_tag =&gt; $1)
                       when String
-                        ancestry.find { |a| a.object_hash[pointer] }
+                        commits(:scope =&gt; :first, :object_hash =&gt; pointer)
                       end
         rescue
-          revision = ancestry.last
+           revision = commits(:scope =&gt; :last)
         end
         
+        revision ||= commits(:scope =&gt; :first)
+        
         if options[:soft]
           revision
         else
-          self.reload_with(revision, :skip_protected =&gt; true)
-          self.save
+          @transitory_revision = revision
+          self.commit! do |s| 
+            s.attributes = revision.cloneable_attributes
+          end
+          @transitory_revision = nil
+          self
         end
       end
-      alias :checkout! :revert_to!
       
-      # this will just return the desired object, rather than forcefully reverting to it
       def checkout(pointer, options = {})
         self.revert_to!(pointer, options.merge({ :soft =&gt; true }))
       end
-      alias :co :checkout
-      alias :revert_to :checkout
       
-      # an array of former commits ending at the base of the branch
-      def ancestry(*args)
-        params = args.extract_options!
-        options = { :with_commits =&gt; true, :conditions =&gt; [&quot;is_head = :head and (branch_id = :branch_id or id = :branch_id)&quot;, { :head =&gt; false, :branch_id =&gt; self.branch_id }], :order =&gt; 'object_created_at desc, id desc' }
+      def commit(options = {}, &amp;block)
+        return unless block_given?
         
-        if params[:count]
-          self.class.count(options)
-        else
-          options.merge!({ :limit =&gt; params[:depth]}) if params[:depth]
-          self.class.find(:all, options)
+        begin
+          commit_mutex(:start)
+          if self.new_record?
+            @stepping_out_of_commit = true
+            self.save
+          end
+          yield(self)
+          self.commit_message = options[:message]
+        ensure
+          commit_mutex(:stop)
         end
-      end
-      alias :ancestors :ancestry
-      
-      # helper for calling ancestry count
-      def count_since_branch
-        self.ancestry(:count =&gt; true)
+        
       end
       
-      # find the root of the current branch
-      def root
-        self.class.find(:first, :with_commits =&gt; true, :conditions =&gt; { :id =&gt; self.branch_id } )
+      def commit!(options = {}, &amp;block)
+        returning(commit(options, &amp;block)) do
+          save!
+        end
       end
       
-      # is this the head commit?
-      def head?
-        is_head?
+      def in_commit?
+        !@commit_mutex.nil?
       end
       
       protected
-      
         def save_with_commit(*args)
-          @commit_parameters ||= args.extract_options!
-          trans_options = args.extract_options!
-          @save_without_commit = true if @commit_parameters.delete :without_commit
-          @branch = trans_options.delete(:branch)
-          @staged_commit_message = trans_options.delete(:commit_message)    # do this better
-          @staged_commit_tag = trans_options.delete(:tag)                   # *really* do this better...
-          save_without_commit
+          @commit_params ||= args.extract_options!
+          @save_without_commit = @commit_params.delete(:without_commit)
+          save_without_commit(*args)
         end
-
+        
         def save_with_commit!(*args)
-          @commit_parameters ||= args.extract_options!
-          trans_options = args.extract_options!
-          @save_without_commit = true if @commit_parameters.delete :without_commit
-          @branch = trans_options.delete(:branch)
-          @staged_commit_message = trans_options.delete(:commit_message)
-          @staged_commit_tag = trans_options.delete(:tag)
-          save_without_commit!
-        end
-      
-        def setup_source_object
-          self.object_hash = self.commit_hash
-          self.is_head = true unless self.branch_id
-          self.object_created_at = Time.now + 1.second
-          self.save :without_commit =&gt; true
+          @commit_params ||= args.extract_options!
+          @save_without_commit = @commit_params.delete(:without_commit)
+          save_without_commit!(*args)
         end
         
-        def clone_associations(receiver)
-          self.associations(true).each do |key, object|
-            if object.is_a?(Array)
-              object.map { |o| n = o.clone; n.set_owner(receiver); n.save; n }
-            else
-              n = object.clone
-              n.set_owner(receiver)
-              n.save
-              n
-            end
+        def setup_commit
+          unless @commit_mutex
+            self.object_hash = self.commit_hash
+            self.commit_created_at = Time.now + 1.second
           end
+          self.commit_tag ||= @commit_tag
         end
         
-        def prepare_to_commit
-          return if self[:object_hash] == self.commit_hash and !@branch
-          self.is_head = false
-          @commit_object = self.to_commit
+        def clone_previous
+          unless @commit_mutex or @stepping_out_of_commit
+            @commit_object = self.to_commit
+            @commit_object = nil if self.commit_hash == @commit_object.commit_hash
+          end
+          @stepping_out_of_commit = false
+          self
         end
         
-        def to_commit
-          rev = self.clone
-          rev.branch_id ||= @branch ? self.id : self.branch_id || self.id
-          rev.source_hash = self.object_hash
-          rev.is_head = true
-
-          self.class.column_names.each do |col|
-            next if self.class.clone_column?(col)
-            val = self.send(&quot;#{col}_changed?&quot;) ? self.send(&quot;#{col}_was&quot;) : self.send(col)
-            self.send(&quot;#{col}=&quot;, val)
+        def clone_associations(object)
+          # there must be a better way to do all of this
+          self.class.associations.each do |assoc|
+              clones =  (@transitory_revision || self).send(&quot;#{assoc}&quot;).map { |a| n = a.clone; a.revert_columns(n); n }
+              self.send(&quot;#{assoc}&quot;).map(&amp;:save)
+              object.send(&quot;#{assoc}=&quot;, clones)
+              if @transitory_revision # need to do this so as to not use the previous commit as a source, but the commit reverting to
+                assoc_id = &quot;#{assoc.to_s.singularize}_ids&quot;
+                original_ids, new_ids = self.send(assoc_id), object.send(assoc_id)
+                self.send(&quot;#{assoc_id}=&quot;, new_ids)
+                object.send(&quot;#{assoc_id}=&quot;, original_ids)
+              end
           end
-
-          rev
         end
         
-        def commit
-          if @commit_object and !@save_without_commit
-            @commit_object.commit_message = @staged_commit_message
-            @commit_object.commit_tag = @staged_commit_tag
+        def save_commit
+          if @commit_object
             @commit_object.save
             self.clone_associations(@commit_object)
-            self.reload_with(@commit_object)
             @commit_object = nil
-            @save_without_commit = nil
-            @branch = nil
-            setup_source_object
           end
         end
         
-        def reload_with(object, options = {})
-          attributes = object.attributes
-          attributes.reject! { |k, v| self.class.skipped_revisionary_attributes.include?(k) } if options[:skip_protected]
-          @attributes.update(attributes)
-          @attributes_cache = {}
-          self
+        def to_commit
+          returning(self.clone) do |obj|
+            self.revert_columns(obj)
+            self.source_hash = obj.commit_hash
+            obj.original_commit_id = self.id
+            self.class.ignored_columns.each { |i| obj.send(&quot;#{i}=&quot;, nil)}
+          end
         end
-      
-    end
-    
-    def self.included(receiver)
-      receiver.send :include, Revisionary::Common
-      receiver.extend         ClassMethods
-      receiver.send :include, InstanceMethods
-      
-      class &lt;&lt; receiver
-        alias_method_chain :find, :commits
-        alias_method_chain :with_scope, :commits
-        alias_method_chain :count, :commits
-      end
-      
-      receiver.instance_eval do
         
-        alias_method_chain :save, :commit
-        alias_method_chain :save!, :commit
-        
-        acts_as_scoped_model :find =&gt; { :conditions =&gt; { :is_head =&gt; true } }
-                
-        after_create :setup_source_object
-        before_update :prepare_to_commit
-        after_update :commit
-        
-      end
+        def commit_mutex(flag)
+          @commit_mutex = flag == :start ? true : false
+        end
+      
     end
     
   end</diff>
      <filename>lib/revisionary/core.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,7 +10,12 @@ require File.join(File.dirname(__FILE__), '..', 'lib', 'revisionary')
 
 class Page &lt; ActiveRecord::Base
   has_many :parts
-  is_revisionary :with =&gt; :parts
+  is_revisionary :with =&gt; :parts, :ignore =&gt; :live_hash
+  
+  def set_live!
+    update_attribute :live_hash, self.object_hash
+  end
+  
 end
 
 class Part &lt; ActiveRecord::Base
@@ -24,14 +29,14 @@ def setup_db
     
     create_table :pages do |t|
       t.string        :name
+      t.string        :live_hash  # a way of having a 'live' commit as opposed to the standard head
       
       t.string        :object_hash
-      t.datetime      :object_created_at
+      t.datetime      :commit_created_at
       t.string        :source_hash
-      t.integer       :branch_id
+      t.integer       :original_commit_id
       t.string        :commit_message
       t.string        :commit_tag
-      t.boolean       :is_head
     end
     
     create_table :parts do |t|</diff>
      <filename>test/helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,116 +11,181 @@ class RevisionaryTest &lt; Test::Unit::TestCase
     teardown_db
   end
   
-  def test_instantiating_a_new_page_with_association
-    page = Page.create
-    part = page.parts.create
-    
-    assert_equal &quot;f62e0ea6edbc4288ff84c8da24f410ecf986229d&quot;, page.commit_hash  # this an empty page with one page part
-    
-    page.parts.first.name = &quot;Testing&quot;
-    
-    assert_equal &quot;e122f9073ed0e1ebfb7ca779a8977944374b21c4&quot;, page.commit_hash  # this an empty page with one page part set to 'testing'
+  def test_for_monitored_associations
+    assert_equal(Page.associations, [:parts])
   end
   
-  def test_that_source_object_knows_itself
-    page = Page.create
+  def test_for_hash_equality
+    page = new_page
+    page.commit! do |p|
+      p.parts.create :name =&gt; 'Body'
+    end
     
-    assert_equal page.commit_hash, page.source_hash
+    assert_equal(page.commit_hash, page.object_hash)
   end
   
-  def test_saving_a_page_and_skipping_equal_commit_hashes
-    page = Page.create :name =&gt; &quot;Home Page&quot;
-    part = page.parts.create :name =&gt; &quot;Body Part&quot;
+  def test_for_consitent_ids
+    page = create_page
+    page_id = page.id
     
-    assert page.head?
+    page.commit! { |p| p.name = 'One' }
+    page.commit! { |p| p.name = 'Two' }
+    page.commit! { |p| p.name = 'Three' }
     
-    page.name = &quot;New Home Page&quot;
-    
-    part.name = &quot;New Body Part&quot;
+    assert_equal(page_id, page.id)
+  end
+
+  def test_for_modifications_in_a_commit_block
+    page = create_page
+    page.commit! do |p|
+      p.name = &quot;Welcome to our website&quot;
+    end
         
-    page.save   # ensure that saving a revisionary model also accounts for watched associations
-    
-    part.name = &quot;Hello from Page Part&quot;
-    
-    page.save
-    page.save   # test that saving unmodified content does nothing   
-    page.save
+    page.commit! do |p|
+      p.name = &quot;Google Inc&quot;
+    end    
     
-    page.name = &quot;Hello from Page&quot;
-    
-    page.save
-    
-    part.name = &quot;Are we done yet?&quot;
-    
-    page.save
-     
-    assert_equal Page.find(:first).root, Page.find(:first).ancestry.last
-    assert_equal Page.find(:first).ancestry(:count =&gt; true), Page.find(:first).ancestry.size
+    assert_equal(Page.find(:first).commits_count, 2)
+    assert_equal(Page.find(:first).name, page.name)
   end
   
-  def test_commit_messages
-    page = Page.create :name =&gt; &quot;Company Profile&quot;, :commit_message =&gt; &quot;Initializing&quot;
-    
-    page.name = &quot;New Company Profile&quot;
-    page.save :commit_message =&gt; &quot;Changed name of page&quot;
-    
-    assert_equal &quot;Changed name of page&quot;, Page.find(:first).commit_message
+  def test_cloning_of_associations
+    page = new_page
+    page.commit! do |p|
+      p.parts.create :name =&gt; 'Body'
+      p.parts.create :name =&gt; 'Sidebar'
+    end
+    
+    page.commit! do |p|
+      p.parts.first.name = 'Body Area'
+      p.name = 'Google Inc'
+    end
+    
+    page.commit! do |p|
+      p.parts.last.name = 'My area'
+    end
+    
+    assert_equal(6, Part.count)
   end
   
-  def test_tagging_of_commits
-    page = Page.create :name =&gt; &quot;Company Profile&quot;
-    
-    page.name = &quot;New Company Profile&quot;
-    page.save :tag =&gt; 'default_commit'
+  def test_ignoring_commiting_duplicates
+    page = new_page
+    page.commit!
+    page.commit! # nothing has changed, this will be ignored
+    page.commit! do |p|
+      page.name = 'Testing name change'
+    end
+    
+    assert_equal(1, page.commits_count)
+  end
+  
+  def test_querying_for_previous_commits
+    page = create_page :name =&gt; 'Previous Commit'
+    page.commit! { |p| p.name = 'Current Commit' }
+    
+    assert_equal('Previous Commit', page.checkout(:previous).name)
+    assert_equal(page.checkout(:previous), page.checkout(:root))
+    assert_equal(page.checkout(:previous), page.checkout(1))
+    assert_equal(page.checkout(:root), page.checkout(10)) # obviously there aren't 10 commits
+  end
+  
+  def test_reverting_a_previous_commit
+    page = create_page :name =&gt; 'Previous Commit'
+    page.commit! { |p| p.name = 'Current Commit' }
+    page.revert_to!(:previous)
     
-    assert_equal 'default_commit', page.tag
+    assert_equal(page.object_hash, page.checkout(:root).object_hash)
   end
   
-  def test_checking_out_old_pages
+  def test_reverting_a_previous_commit_with_associations
+    page = new_page :name =&gt; 'Previous Commit'
+    page.commit! do |p|
+      p.parts.create :name =&gt; 'Body'
+      p.parts.create :name =&gt; 'Sidebar'
+    end
     
-    page = Page.create :name =&gt; &quot;About Us&quot;
+    page.commit! do |p|
+      p.name = 'Current Commit'
+      p.parts.first.name = 'New Body'
+      p.parts.last.name = 'New Sidebar'
+    end
     
-    page.name = &quot;Beginner About Us&quot;
-    page.save :tag =&gt; &quot;beginner&quot;
+    page.commit! do |p|
+      p.name = 'Final Commit'
+      p.parts.first.name = 'Final Body'
+      p.parts.last.name = 'Final Sidebar'
+    end
     
-    page.update_attribute :name, &quot;A Newer About Us&quot;
-    page.update_attribute :name, &quot;An Even Better About Us&quot;
+    page.revert_to!(:previous)
     
-    assert_equal &quot;About Us&quot;, page.co(3).name
-    assert_equal &quot;A Newer About Us&quot;, page.checkout(:previous).name
-    assert_equal &quot;Beginner About Us&quot;, page.checkout(&quot;beginner&quot;).name
-        
+    assert_equal('Current Commit', page.name)
+    
+    page.revert_to!(:root)
+    
+    assert_equal('Previous Commit', page.name)
   end
   
-  def test_reverting
+  def test_ignored_attributes
+    page = create_page :name =&gt; 'Home Page'
     
-    page = Page.create :name =&gt; &quot;About Us&quot;
-    part = page.parts.create :name =&gt; &quot;Test&quot;
+    page.set_live! # this is a method outside of Revisionary included in the Page class defined in helper.rb
     
-    page.name = &quot;New About Us&quot;
-    part.name = &quot;New Test&quot;
-    page.save
+    page.commit! do |p|
+      p.name = 'My Home Page'
+    end
     
-    page.revert_to!(:root)
+    page.commit! do |p|
+      p.name = 'Google Inc.'
+    end
     
-    assert_equal Page.find(:first).checkout(:root).name, Page.find(:first).name
-
-  end
-
-  def test_multiple
+    page.update_attribute :live_hash, page.object_hash
     
-    home = Page.create :name =&gt; &quot;Home&quot;
-    about = Page.create :name =&gt; &quot;About Us&quot;
+    assert_nil page.checkout(:previous).live_hash
+    assert page.live_hash
+  end
+  
+  def test_query_for_live_page_by_live_hash
+    # if you intend on having a live, approved version of a record in comparison to the head, this is useful
+    page = create_page :name =&gt; 'Home Page'
     
-    home.name = &quot;Home Page&quot;
-    home.save :commit_message =&gt; &quot;Better title&quot;
+    page.set_live!
     
-    home.name = &quot;Welcome to our company!&quot;
-    home.save
+    page.commit! { |p| p.name = 'Welcome Page' } # this is not approved
     
-    assert_equal home, Page.find_by_branch(1)
-    assert_equal about, Page.find_by_name(&quot;About Us&quot;)    
+    assert_equal('Welcome Page', page.name)
+    assert_equal('Home Page', page.checkout(page.live_hash).name)
     
   end
+  
+  # def test_commit_messages
+  #   page = new_page
+  #   page.commit! :message =&gt; 'Made some changes' do |p|
+  #     p.name = 'Google Inc'
+  #   end
+  #   
+  #   assert_equal('Made some changes', page.commit_message)
+  # end
+  # 
+  # def test_tagging
+  #   page = create_page
+  #   page.commit! :tag =&gt; 'final' do |p|
+  #     p.name = 'Final Commit'
+  #   end
+  #   
+  #   page.commit! { |p| p.name = 'Maybe not' }
+  #   
+  #   assert_equal(Page.find(:all, :with_commits =&gt; true), [])
+  #   assert_equal('Final Commit', page.checkout('tag:final').name)
+  # end
+  
+  def new_page(options = {})
+    Page.new({:name =&gt; &quot;Home Page&quot;}.merge(options))
+  end
+  
+  def create_page(options = {})
+    page = new_page(options)
+    page.save
+    page
+  end
 
 end</diff>
      <filename>test/revisionary_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>984b8ed4a9982032112823d018e70d5a159a43cb</id>
    </parent>
  </parents>
  <author>
    <name>Brennan Dunn</name>
    <email>brennandunn@brennan-dunns-macbook-pro-67.local</email>
  </author>
  <url>http://github.com/brennandunn/revisionary/commit/5c800fea4c09777c54e71d5eb2c6c6d2da67be74</url>
  <id>5c800fea4c09777c54e71d5eb2c6c6d2da67be74</id>
  <committed-date>2008-06-06T17:05:22-07:00</committed-date>
  <authored-date>2008-06-06T17:05:22-07:00</authored-date>
  <message>Update from live project</message>
  <tree>c1f5a21007fbbaa4f241e757eec2d66aa0827c95</tree>
  <committer>
    <name>Brennan Dunn</name>
    <email>brennandunn@brennan-dunns-macbook-pro-67.local</email>
  </committer>
</commit>
