--- includes/taxonomy.old.inc	2010-08-12 17:34:08.000000000 +0100
+++ includes/taxonomy.inc	2011-01-11 10:03:18.000000000 +0000
@@ -16,18 +16,32 @@ function taxonomy_diff($old_node, $new_n
   $new_taxonomy = array();
   if (isset($old_node->taxonomy) && $old_node->taxonomy) {
     foreach ($old_node->taxonomy as $term) {
-      $old_taxonomy[] = $term->name;
+      $vocab = taxonomy_vocabulary_load($term->vid);
+      $old_taxonomy[] = $vocab->name .' -> '. $term->name;
     }
   }
   if (isset($new_node->taxonomy) && $new_node->taxonomy) {
     foreach ($new_node->taxonomy as $id => $entry) {
-      if (is_array($entry)) {
-        // During editing the taxonomy is built up as a list of vocabulary ids as keys
-        // and a list of term ids per array entry.
+      if (empty($entry)) {
+        continue; // Skip over empty entries.
+      }
+      if (is_object($entry)) {
+        // When diffing revisions, taxonomy is an array of term objects.
+        // Currently, there's no way to diff revisions because taxonomy isn't versioned,
+        // but we build the list anyway.
+        $vocab = taxonomy_vocabulary_load($entry->vid);
+        $new_taxonomy[] = $vocab->name .' -> '. $entry->name;
+      }
+      elseif (is_array($entry)) {
+        // During editing, taxonomy will be an array for multi-select and
+        // freetagging vocabularies.
         if (is_numeric($id)) {
+          // A multi-select taxonomy is built up as a list of vocabulary ids as keys and
+          // a list of term ids per array entry.
           foreach ($entry as $tid) {
             $term = taxonomy_get_term($tid);
-            $new_taxonomy[] = $term->name;
+            $vocab = taxonomy_vocabulary_load($term->vid);
+            $new_taxonomy[] = $vocab->name .' -> '. $term->name;
           }
         }
         else {
@@ -35,10 +49,15 @@ function taxonomy_diff($old_node, $new_n
           // vocabularies. These are stored as an array which map the vocabulary id to
           // a string of terms.
           foreach ($entry as $taglist) {
+            if (empty($taglist)) {
+              continue; // Skip over empty taglists.
+            }
             // The regular expression is taken from taxonomy.module.
             preg_match_all('%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x', $taglist, $matches);
+            $vocab = taxonomy_vocabulary_load(key($entry));
+            sort($matches[1]);
             foreach ($matches[1] as $term) {
-              $new_taxonomy[] = $term;
+              $new_taxonomy[] = $vocab->name .' -> '. $term;
             }
           }
         }
@@ -46,14 +65,20 @@ function taxonomy_diff($old_node, $new_n
       elseif (is_numeric($entry)) {
         // During editing, taxonomy is a single id.
         $term = taxonomy_get_term($entry);
-        $new_taxonomy[] = $term->name;
+        $vocab = taxonomy_vocabulary_load($term->vid);
+        $new_taxonomy[] = $vocab->name .' -> '. $term->name;
       }
       else {
         // Not during editing the taxonomy list is a list of terms.
-        $new_taxonomy[] = $entry->name;
+        $vocab = taxonomy_vocabulary_load($entry->vid);
+        $new_taxonomy[] = $vocab->name .' -> '. $entry->name;
       }
     }
   }
+  // Make sure terms are in a consistent order for the diff.
+  sort($old_taxonomy);
+  sort($new_taxonomy)
+  
   $result['taxonomy'] = array(
     '#name' => t('Taxonomy'),
     '#old' => $old_taxonomy,
