Index: views_bulk_operations.module
===================================================================
--- views_bulk_operations.module	(revision 498)
+++ views_bulk_operations.module	(working copy)
@@ -274,10 +274,15 @@
       else {
         unset($selected['select_all']);
       }
+      if ($operation['custom_confirmation']) {
+        $form = $operation['custom_confirmation'](array_filter($selected), $plugin->view);
+      }
+      else {
       $form = confirm_form($form,
         t('Are you sure you want to perform \'%action\' on selected rows?', array('%action' => $operation['label'])),
         $query ? array('path' => $_GET['q'], 'query' => $query) : array('path' => $_GET['q']),
         theme('views_bulk_operations_confirmation', array_filter($selected), $plugin->view)); 
+      }
       $plugin->view->pager['use_pager'] = FALSE;
       $plugin->view->exposed_widgets = NULL;
       break;
Index: views_bulk_operations_plugin_style.inc
===================================================================
--- views_bulk_operations_plugin_style.inc	(revision 498)
+++ views_bulk_operations_plugin_style.inc	(working copy)
@@ -154,6 +154,7 @@
         'object'             => $operation['type'],
         'aggregate'          => $operation['aggregate'],
         'modifies_object'    => isset($operation['behavior']) && in_array('changes_node_property', $operation['behavior']),
+        'custom_confirmation' => $operation['custom_confirmation'],
       );
     }
 
Index: node_merge.action.inc
===================================================================
--- node_merge.action.inc	(revision 0)
+++ node_merge.action.inc	(revision 0)
@@ -0,0 +1,79 @@
+<?php
+
+function node_merge_action_info() {
+  return array('node_merge_action' => array(
+    'type' => 'node',
+    'description' => t('Merge duplicate nodes'),
+    'configurable' => FALSE,
+    'behaviour' => array('changes_node_property'),
+    'aggregate' => TRUE,
+    'custom_confirmation' => 'node_merge_action_form',
+    'modifies_object' => TRUE,
+  ));
+}
+
+function node_merge_action(&$node, $context) {
+  switch ($context['do']) {
+    case 'merge':
+      break;
+  }
+}
+
+function node_merge_action_submit($form, $form_state) {
+  return array(
+    'do' => $form_state['values']['do'],
+    'terms' => $form_state['values']['terms'],
+  );
+}
+
+function node_merge_action_form($objects, $view) {
+  $form = array();
+  $i = 0;
+  $info = _views_bulk_operations_object_info_for_view($view);
+
+  foreach ($objects as $oid) {
+    if ($object = call_user_func($info['load'], $oid)) {
+      $nodes[$oid] = $object->{$info['title']};
+    }
+  }
+
+  $form['nodes'] = array(
+    '#type' => 'radios',
+    '#options' => $nodes,
+  );
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Merge'),
+  );
+
+  $form['#theme'] = 'node_merge_action_form';
+  $form['#submit'] = array('node_merge_action_form_submit');
+
+  return $form;
+}
+
+function node_merge_action_validate($form, $form_state) {
+
+}
+
+function node_merge_action_form_submit($form, $form_state) {
+  if ($form_state['values']['op'] == t('Merge')) {
+    $primary = $form_state['values']['nodes'];
+    foreach ($form_state['storage'][1]['objects'] as $nid) {
+      if ($nid != $primary && $nid != 0) {
+        $others[] = $nid;
+      }
+    }
+    drupal_set_message(t('Node @nid made primary', array('@nid' => $nid)));
+  }
+
+  // Now loop through $others and grab any comments etc and reassign to $primary
+
+  drupal_goto();
+}
+
+function theme_node_merge_action_form() {
+
+  return $output;
+}
\ No newline at end of file
