diff --git a/thunar/thunar-application.c b/thunar/thunar-application.c
index debf20f2843666b66e29de663daa95785b84f2a1..0135a127a4d40e807863fcd4cb1fe612ab6356be 100644
--- a/thunar/thunar-application.c
+++ b/thunar/thunar-application.c
@@ -57,6 +57,7 @@
 #include <thunar/thunar-renamer-dialog.h>
 #include <thunar/thunar-thumbnail-cache.h>
 #include <thunar/thunar-thumbnailer.h>
+#include <thunar/thunar-transfer-job.h>
 #include <thunar/thunar-util.h>
 #include <thunar/thunar-view.h>
 #include <thunar/thunar-session-client.h>
@@ -144,6 +145,7 @@ static void           thunar_application_collect_and_launch     (ThunarApplicati
                                                                  GFile                  *target_file,
                                                                  gboolean                update_source_folders,
                                                                  gboolean                update_target_folders,
+                                                                 ThunarOperationLogMode  log_mode,
                                                                  GClosure               *new_files_closure);
 static void           thunar_application_launch_finished        (ThunarJob              *job,
                                                                  GList                  *containing_folders);
@@ -156,6 +158,7 @@ static void           thunar_application_launch                 (ThunarApplicati
                                                                  GList                  *target_path_list,
                                                                  gboolean                update_source_folders,
                                                                  gboolean                update_target_folders,
+                                                                 ThunarOperationLogMode  log_mode,
                                                                  GClosure               *new_files_closure);
 #ifdef HAVE_GUDEV
 static void           thunar_application_uevent                 (GUdevClient            *client,
@@ -806,16 +809,17 @@ thunar_application_accel_map_changed (ThunarApplication *application)
 
 
 static void
-thunar_application_collect_and_launch (ThunarApplication *application,
-                                       gpointer           parent,
-                                       const gchar       *icon_name,
-                                       const gchar       *title,
-                                       Launcher           launcher,
-                                       GList             *source_file_list,
-                                       GFile             *target_file,
-                                       gboolean           update_source_folders,
-                                       gboolean           update_target_folders,
-                                       GClosure          *new_files_closure)
+thunar_application_collect_and_launch (ThunarApplication      *application,
+                                       gpointer                parent,
+                                       const gchar            *icon_name,
+                                       const gchar            *title,
+                                       Launcher                launcher,
+                                       GList                  *source_file_list,
+                                       GFile                  *target_file,
+                                       gboolean                update_source_folders,
+                                       gboolean                update_target_folders,
+                                       ThunarOperationLogMode  log_mode,
+                                       GClosure               *new_files_closure)
 {
   GFile  *file;
   GError *err = NULL;
@@ -861,7 +865,7 @@ thunar_application_collect_and_launch (ThunarApplication *application,
     {
       /* launch the operation */
       thunar_application_launch (application, parent, icon_name, title, launcher,
-                                 source_file_list, target_file_list, update_source_folders, update_target_folders, new_files_closure);
+                                 source_file_list, target_file_list, update_source_folders, update_target_folders, log_mode, new_files_closure);
     }
 
   /* release the target path list */
@@ -911,16 +915,17 @@ thunar_application_launch_finished (ThunarJob  *job,
 
 
 static void
-thunar_application_launch (ThunarApplication *application,
-                           gpointer           parent,
-                           const gchar       *icon_name,
-                           const gchar       *title,
-                           Launcher           launcher,
-                           GList             *source_file_list,
-                           GList             *target_file_list,
-                           gboolean           update_source_folders,
-                           gboolean           update_target_folders,
-                           GClosure          *new_files_closure)
+thunar_application_launch (ThunarApplication     *application,
+                           gpointer               parent,
+                           const gchar           *icon_name,
+                           const gchar           *title,
+                           Launcher               launcher,
+                           GList                 *source_file_list,
+                           GList                 *target_file_list,
+                           gboolean               update_source_folders,
+                           gboolean               update_target_folders,
+                           ThunarOperationLogMode log_mode,
+                           GClosure              *new_files_closure)
 {
   GtkWidget *dialog;
   GdkScreen *screen;
@@ -941,6 +946,8 @@ thunar_application_launch (ThunarApplication *application,
   if (update_target_folders)
     parent_folder_list = g_list_concat (parent_folder_list, thunar_g_file_list_get_parents (target_file_list));
 
+  thunar_job_set_log_mode (job, log_mode);
+
   /* connect a callback to instantly refresh the parent folders after the operation finished */
   g_signal_connect (G_OBJECT (job), "finished",
                     G_CALLBACK (thunar_application_launch_finished),
@@ -2066,7 +2073,7 @@ thunar_application_copy_to (ThunarApplication *application,
   /* launch the operation */
   thunar_application_launch (application, parent, "edit-copy",
                              _("Copying files..."), thunar_io_jobs_copy_files,
-                             source_file_list, target_file_list, FALSE, TRUE, new_files_closure);
+                             source_file_list, target_file_list, FALSE, TRUE, THUNAR_OPERATION_LOG_OPERATIONS, new_files_closure);
 }
 
 
@@ -2131,6 +2138,7 @@ thunar_application_copy_into (ThunarApplication *application,
                                          title, thunar_io_jobs_copy_files,
                                          source_file_list, target_file,
                                          FALSE, TRUE,
+                                         THUNAR_OPERATION_LOG_OPERATIONS,
                                          new_files_closure);
 
   /* free */
@@ -2184,6 +2192,7 @@ thunar_application_link_into (ThunarApplication *application,
                                          title, thunar_io_jobs_link_files,
                                          source_file_list, target_file,
                                          FALSE, TRUE,
+                                         THUNAR_OPERATION_LOG_OPERATIONS,
                                          new_files_closure);
 
   /* free the title */
@@ -2198,6 +2207,7 @@ thunar_application_link_into (ThunarApplication *application,
  * @parent            : a #GdkScreen, a #GtkWidget or %NULL.
  * @source_file_list  : the list of #GFile<!---->s that should be moved.
  * @target_file       : the target directory.
+ * @log_mode          : A #ThunarOperationLogMode enum to control logging.
  * @new_files_closure : a #GClosure to connect to the job's "new-files" signal,
  *                      which will be emitted when the job finishes with the
  *                      list of #GFile<!---->s created by the job, or
@@ -2208,11 +2218,12 @@ thunar_application_link_into (ThunarApplication *application,
  * interaction.
  **/
 void
-thunar_application_move_into (ThunarApplication *application,
-                              gpointer           parent,
-                              GList             *source_file_list,
-                              GFile             *target_file,
-                              GClosure          *new_files_closure)
+thunar_application_move_into (ThunarApplication      *application,
+                              gpointer                parent,
+                              GList                  *source_file_list,
+                              GFile                  *target_file,
+                              ThunarOperationLogMode  log_mode,
+                              GClosure               *new_files_closure)
 {
   gchar *display_name;
   gchar *title;
@@ -2251,6 +2262,7 @@ thunar_application_move_into (ThunarApplication *application,
                                              thunar_io_jobs_move_files,
                                              source_file_list, target_file,
                                              TRUE, TRUE,
+                                             log_mode,
                                              new_files_closure);
 
       /* free the title */
@@ -2260,6 +2272,42 @@ thunar_application_move_into (ThunarApplication *application,
 
 
 
+/**
+ * thunar_application_move_files:
+ * @application       : a #ThunarApplication.
+ * @parent            : a #GdkScreen, a #GtkWidget or %NULL.
+ * @source_file_list  : the list of #GFile<!---->s that should be moved.
+ * @target_file_list  : the list of #GFile<!---->s that the files should be moved to
+ * @log_mode          : a #ThunarOperationLogMode controlling the logging of the operation.
+ * @new_files_closure : a #GClosure to connect to the job's "new-files" signal,
+ *                      which will be emitted when the job finishes with the
+ *                      list of #GFile<!---->s created by the job, or
+ *                      %NULL if you're not interested in the signal.
+ *
+ * Moves all the files in the source file list to the files given in the target file list.
+ **/
+void
+thunar_application_move_files (ThunarApplication       *application,
+                               gpointer                 parent,
+                               GList                   *source_file_list,
+                               GList                   *target_file_list,
+                               ThunarOperationLogMode   log_mode,
+                               GClosure                *new_files_closure)
+{
+  _thunar_return_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WIDGET (parent));
+  _thunar_return_if_fail (THUNAR_IS_APPLICATION (application));
+ 
+  thunar_application_launch (application, parent,
+                             "stock_folder-move", _("Moving files ..."),
+                             thunar_io_jobs_move_files,
+                             source_file_list, target_file_list,
+                             TRUE, TRUE,
+                             log_mode,
+                             new_files_closure);
+}
+
+
+
 static ThunarJob *
 unlink_stub (GList *source_path_list,
              GList *target_path_list)
@@ -2361,7 +2409,7 @@ thunar_application_unlink_files (ThunarApplication *application,
           /* launch the "Delete" operation */
           thunar_application_launch (application, parent, "edit-delete",
                                      _("Deleting files..."), unlink_stub,
-                                     path_list, path_list, TRUE, FALSE, NULL);
+                                     path_list, path_list, TRUE, FALSE, THUNAR_OPERATION_LOG_OPERATIONS, NULL);
         }
     }
   else
@@ -2396,7 +2444,7 @@ thunar_application_trash (ThunarApplication *application,
 
   thunar_application_launch (application, parent, "user-trash-full",
                              _("Moving files into the trash..."), trash_stub,
-                             file_list, NULL, TRUE, FALSE, NULL);
+                             file_list, NULL, TRUE, FALSE, THUNAR_OPERATION_LOG_OPERATIONS, NULL);
 }
 
 
@@ -2442,7 +2490,7 @@ thunar_application_creat (ThunarApplication *application,
   /* launch the operation */
   thunar_application_launch (application, parent, "document-new",
                              _("Creating files..."), creat_stub,
-                             &template_list, file_list, FALSE, TRUE, new_files_closure);
+                             &template_list, file_list, FALSE, TRUE, THUNAR_OPERATION_LOG_OPERATIONS, new_files_closure);
 }
 
 
@@ -2481,7 +2529,7 @@ thunar_application_mkdir (ThunarApplication *application,
   /* launch the operation */
   thunar_application_launch (application, parent, "folder-new",
                              _("Creating directories..."), mkdir_stub,
-                             file_list, file_list, TRUE, FALSE, new_files_closure);
+                             file_list, file_list, TRUE, FALSE, THUNAR_OPERATION_LOG_OPERATIONS, new_files_closure);
 }
 
 
@@ -2547,7 +2595,7 @@ thunar_application_empty_trash (ThunarApplication *application,
       /* launch the operation */
       thunar_application_launch (application, parent, "user-trash",
                                  _("Emptying the Trash..."),
-                                 unlink_stub, &file_list, NULL, TRUE, FALSE, NULL);
+                                 unlink_stub, &file_list, NULL, TRUE, FALSE, THUNAR_OPERATION_LOG_OPERATIONS, NULL);
 
       /* cleanup */
       g_object_unref (file_list.data);
@@ -2618,7 +2666,7 @@ thunar_application_restore_files (ThunarApplication *application,
       /* launch the operation */
       thunar_application_launch (application, parent, "stock_folder-move",
                                  _("Restoring files..."), thunar_io_jobs_restore_files,
-                                 source_path_list, target_path_list, TRUE, TRUE, new_files_closure);
+                                 source_path_list, target_path_list, TRUE, TRUE, THUNAR_OPERATION_LOG_OPERATIONS, new_files_closure);
     }
 
   /* free path lists */
diff --git a/thunar/thunar-application.h b/thunar/thunar-application.h
index 8c180e8cf81917b3c6dc36868e396b41b5fbbe0e..6bd4df6ca7bdf6d0a2ffc8ab212dd029cfb47406 100644
--- a/thunar/thunar-application.h
+++ b/thunar/thunar-application.h
@@ -23,6 +23,7 @@
 #ifndef __THUNAR_APPLICATION_H__
 #define __THUNAR_APPLICATION_H__
 
+#include <thunar/thunar-job-operation.h>
 #include <thunar/thunar-window.h>
 #include <thunar/thunar-thumbnail-cache.h>
 
@@ -115,11 +116,19 @@ void                  thunar_application_link_into                 (ThunarApplic
                                                                     GFile             *target_file,
                                                                     GClosure          *new_files_closure);
 
-void                  thunar_application_move_into                 (ThunarApplication *application,
-                                                                    gpointer           parent,
-                                                                    GList             *source_file_list,
-                                                                    GFile             *target_file,
-                                                                    GClosure          *new_files_closure);
+void                  thunar_application_move_into                 (ThunarApplication      *application,
+                                                                    gpointer                parent,
+                                                                    GList                  *source_file_list,
+                                                                    GFile                  *target_file,
+                                                                    ThunarOperationLogMode  log_mode,
+                                                                    GClosure               *new_files_closure);
+
+void                  thunar_application_move_files                (ThunarApplication       *application,
+                                                                    gpointer                 parent,
+                                                                    GList                   *source_file_list,
+                                                                    GList                   *target_file_list,
+                                                                    ThunarOperationLogMode   log_mode,
+                                                                    GClosure                *new_files_closure);
 
 void                  thunar_application_unlink_files              (ThunarApplication *application,
                                                                     gpointer           parent,
diff --git a/thunar/thunar-clipboard-manager.c b/thunar/thunar-clipboard-manager.c
index cae6c4e1ddd14a485e4f05777710d464662a5a99..8307ef06e57b45fe173d5f789db75c731625334d 100644
--- a/thunar/thunar-clipboard-manager.c
+++ b/thunar/thunar-clipboard-manager.c
@@ -332,7 +332,7 @@ thunar_clipboard_manager_contents_received (GtkClipboard     *clipboard,
       if (G_LIKELY (path_copy))
         thunar_application_copy_into (application, request->widget, file_list, request->target_file, request->new_files_closure);
       else
-        thunar_application_move_into (application, request->widget, file_list, request->target_file, request->new_files_closure);
+        thunar_application_move_into (application, request->widget, file_list, request->target_file, THUNAR_OPERATION_LOG_OPERATIONS, request->new_files_closure);
       g_object_unref (G_OBJECT (application));
       thunar_g_list_free_full (file_list);
 
diff --git a/thunar/thunar-dbus-service.c b/thunar/thunar-dbus-service.c
index e516fef842b892cbe591bafbf9b6de836cf05d15..11587422b9d274cd83c0d1bcd7075c028e8ec3f8 100644
--- a/thunar/thunar-dbus-service.c
+++ b/thunar/thunar-dbus-service.c
@@ -1241,6 +1241,7 @@ thunar_dbus_service_transfer_files (ThunarDBusTransferMode transfer_mode,
             case THUNAR_DBUS_TRANSFER_MODE_MOVE_INTO:
               thunar_application_move_into (application, screen,
                                             source_file_list, target_file_list->data,
+                                            THUNAR_OPERATION_LOG_OPERATIONS,
                                             NULL);
               break;
             case THUNAR_DBUS_TRANSFER_MODE_LINK_INTO:
diff --git a/thunar/thunar-dnd.c b/thunar/thunar-dnd.c
index 964d311f98f504df0696ac3223d51ee9ff312779..bf1ba316e1b840585381f2a7a9b59f64c5135747 100644
--- a/thunar/thunar-dnd.c
+++ b/thunar/thunar-dnd.c
@@ -231,7 +231,7 @@ thunar_dnd_perform (GtkWidget    *widget,
           break;
 
         case GDK_ACTION_MOVE:
-          thunar_application_move_into (application, widget, file_list, thunar_file_get_file (file), new_files_closure);
+          thunar_application_move_into (application, widget, file_list, thunar_file_get_file (file), THUNAR_OPERATION_LOG_OPERATIONS, new_files_closure);
           break;
 
         case GDK_ACTION_LINK:
diff --git a/thunar/thunar-job-operation.c b/thunar/thunar-job-operation.c
index b7a8fbb08ff9cb72099db3b804c1c6fe1dc4798a..25a511200f0a2d46c273097791dedd0dc1541eba 100644
--- a/thunar/thunar-job-operation.c
+++ b/thunar/thunar-job-operation.c
@@ -17,6 +17,7 @@
  */
 
 #include <thunar/thunar-application.h>
+#include <thunar/thunar-dialogs.h>
 #include <thunar/thunar-enum-types.h>
 #include <thunar/thunar-job-operation.h>
 #include <thunar/thunar-private.h>
@@ -51,6 +52,7 @@ struct _ThunarJobOperation
   ThunarJobOperationKind  operation_kind;
   GList                  *source_file_list;
   GList                  *target_file_list;
+  GList                  *overwritten_file_list;
 };
 
 G_DEFINE_TYPE (ThunarJobOperation, thunar_job_operation, G_TYPE_OBJECT)
@@ -77,6 +79,7 @@ thunar_job_operation_init (ThunarJobOperation *self)
   self->operation_kind = THUNAR_JOB_OPERATION_KIND_COPY;
   self->source_file_list = NULL;
   self->target_file_list = NULL;
+  self->overwritten_file_list = NULL;
 }
 
 
@@ -90,6 +93,7 @@ thunar_job_operation_dispose (GObject *object)
 
   g_list_free_full (op->source_file_list, g_object_unref);
   g_list_free_full (op->target_file_list, g_object_unref);
+  g_list_free_full (op->overwritten_file_list, g_object_unref);
 
   (*G_OBJECT_CLASS (thunar_job_operation_parent_class)->dispose) (object);
 }
@@ -159,6 +163,24 @@ thunar_job_operation_add (ThunarJobOperation *job_operation,
 
 
 
+/***
+ * thunar_job_operation_overwrite:
+ * @job_operation:    a #ThunarJobOperation
+ * @overwritten_file: a #GFile representing the file that has been overwritten
+ *
+ * Logs a file overwritten as a part of an operation.
+ **/
+void
+thunar_job_operation_overwrite (ThunarJobOperation *job_operation,
+                                GFile              *overwritten_file)
+{
+  _thunar_return_if_fail (THUNAR_IS_JOB_OPERATION (job_operation));
+
+  job_operation->overwritten_file_list = thunar_g_list_append_deep (job_operation->overwritten_file_list, overwritten_file);
+}
+
+
+
 /**
  * thunar_job_operation_commit:
  * @job_operation: a #ThunarJobOperation
@@ -171,10 +193,6 @@ thunar_job_operation_commit (ThunarJobOperation *job_operation)
 {
   _thunar_return_if_fail (THUNAR_IS_JOB_OPERATION (job_operation));
 
-  /* do not register an 'empty' job operation */
-  if (job_operation->source_file_list == NULL && job_operation->target_file_list == NULL)
-    return;
-
   /* We only keep one job operation commited in the job operation list, so we have to free the
    * memory for the job operation in the list, if any, stored in before we commit the new one. */
   thunar_g_list_free_full (job_operation_list);
@@ -195,6 +213,10 @@ thunar_job_operation_undo (void)
 {
   ThunarJobOperation *operation_marker;
   ThunarJobOperation *inverted_operation;
+  GEnumClass         *enum_class;
+  GEnumValue         *enum_value;
+  GString            *warning_body;
+  gchar              *file_uri;
 
   /* do nothing in case there is no job operation to undo */
   if (job_operation_list == NULL)
@@ -203,9 +225,48 @@ thunar_job_operation_undo (void)
   /* the 'marked' operation */
   operation_marker = job_operation_list->data;
 
-  inverted_operation = thunar_job_operation_new_invert (operation_marker);
-  thunar_job_operation_execute (inverted_operation);
-  g_object_unref (inverted_operation);
+  /* the enum value of the operation kind, which will be used to get its nick name */
+  enum_class = g_type_class_ref (THUNAR_TYPE_JOB_OPERATION_KIND);
+  enum_value = g_enum_get_value (enum_class, operation_marker->operation_kind);
+
+  /* warn the user if the previous operation is empty, since then there is nothing to undo */
+  if (operation_marker->source_file_list == NULL && operation_marker->target_file_list == NULL)
+    {
+
+      xfce_dialog_show_warning (NULL,
+                                _("The operation you are trying to undo does not have any files "
+                                  "associated with it, and thus cannot be undone. "),
+                                _("%s operation cannot be undone"), enum_value->value_nick);
+    }
+  else
+    {
+      /* if there were files overwritten in the operation, warn about them */
+      if (operation_marker->overwritten_file_list != NULL)
+        {
+          gint index;
+
+          index = 1; /* one indexed for the dialog */
+          warning_body = g_string_new (_("The following files were overwritten in the operation "
+                                         "you are trying to undo and cannot be restored:\n"));
+
+          for (GList *lp = operation_marker->overwritten_file_list; lp != NULL; lp = lp->next, index++)
+            {
+              file_uri = g_file_get_uri (lp->data);
+              g_string_append_printf (warning_body, "%d. %s\n", index, file_uri);
+              g_free (file_uri);
+            }
+
+          xfce_dialog_show_warning (NULL,
+                                    warning_body->str,
+                                    _("%s operation can only be partially undone"), enum_value->value_nick);
+
+          g_string_free (warning_body, TRUE);
+        }
+
+      inverted_operation = thunar_job_operation_new_invert (operation_marker);
+      thunar_job_operation_execute (inverted_operation);
+      g_object_unref (inverted_operation);
+    }
 
   /* Completely clear the job operation list on undo, this is because we only store the single
    * most recent operation, and we do not want it to be available to undo *again* after it has
@@ -239,6 +300,13 @@ thunar_job_operation_new_invert (ThunarJobOperation *job_operation)
         inverted_operation->source_file_list = thunar_g_list_copy_deep (job_operation->target_file_list);
         break;
 
+      case THUNAR_JOB_OPERATION_KIND_MOVE:
+        inverted_operation = g_object_new (THUNAR_TYPE_JOB_OPERATION, NULL);
+        inverted_operation->operation_kind = THUNAR_JOB_OPERATION_KIND_MOVE;
+        inverted_operation->source_file_list = thunar_g_list_copy_deep (job_operation->target_file_list);
+        inverted_operation->target_file_list = thunar_g_list_copy_deep (job_operation->source_file_list);
+        break;
+
       default:
         g_assert_not_reached ();
         break;
@@ -261,6 +329,7 @@ thunar_job_operation_execute (ThunarJobOperation *job_operation)
   GList             *thunar_file_list = NULL;
   GError            *error            = NULL;
   ThunarFile        *thunar_file;
+  GFile             *parent_dir;
 
   _thunar_return_if_fail (THUNAR_IS_JOB_OPERATION (job_operation));
 
@@ -287,7 +356,7 @@ thunar_job_operation_execute (ThunarJobOperation *job_operation)
 
             if (!THUNAR_IS_FILE (thunar_file))
               {
-                g_error ("One of the files in the job operation list did not convert to a valid ThunarFile");
+                g_warning ("One of the files in the job operation list did not convert to a valid ThunarFile");
                 continue;
               }
 
@@ -299,6 +368,39 @@ thunar_job_operation_execute (ThunarJobOperation *job_operation)
         thunar_g_list_free_full (thunar_file_list);
         break;
 
+      case THUNAR_JOB_OPERATION_KIND_MOVE:
+
+        /* ensure that all the targets have parent directories which exist */
+        for (GList *lp = job_operation->target_file_list; lp != NULL; lp = lp->next)
+          {
+            parent_dir = g_file_get_parent (lp->data);
+            g_file_make_directory_with_parents (parent_dir, NULL, &error);
+            g_object_unref (parent_dir);
+
+            if (error != NULL)
+            {
+              /* there is no issue if the target directory already exists */
+              if (error->code == G_IO_ERROR_EXISTS)
+                {
+                  g_clear_error (&error);
+                  continue;
+                }
+
+              /* output the error message to console otherwise and abort */
+              g_warning ("Error while moving files: %s\n"
+                           "Aborting operation\n",
+                         error->message);
+              g_clear_error (&error);
+              g_object_unref (application);
+              return;
+            }
+          }
+
+        thunar_application_move_files (application, NULL,
+                                       job_operation->source_file_list, job_operation->target_file_list,
+                                       THUNAR_OPERATION_LOG_NO_OPERATIONS, NULL);
+        break;
+
       default:
         _thunar_assert_not_reached ();
         break;
diff --git a/thunar/thunar-job-operation.h b/thunar/thunar-job-operation.h
index 1c6b19925fd5d9976296cfff92df9ec229a0cc10..e04664c1f2b56a83f7bb6d89420fc00278e23c7f 100644
--- a/thunar/thunar-job-operation.h
+++ b/thunar/thunar-job-operation.h
@@ -27,13 +27,26 @@ G_BEGIN_DECLS
 #define THUNAR_TYPE_JOB_OPERATION (thunar_job_operation_get_type ())
 G_DECLARE_FINAL_TYPE (ThunarJobOperation, thunar_job_operation, THUNAR, JOB_OPERATION, GObject)
 
-G_END_DECLS
+/**
+ * ThunarOperationLogMode:
+ *
+ * Specify control logging for operations.
+ **/
+typedef enum
+{
+  THUNAR_OPERATION_LOG_NO_OPERATIONS,
+  THUNAR_OPERATION_LOG_OPERATIONS,
+} ThunarOperationLogMode;
 
 ThunarJobOperation    *thunar_job_operation_new          (ThunarJobOperationKind kind);
 void                   thunar_job_operation_add          (ThunarJobOperation    *job_operation,
                                                           GFile                 *source_file,
                                                           GFile                 *target_file);
+void                   thunar_job_operation_overwrite    (ThunarJobOperation    *job_operation,
+                                                          GFile                 *overwritten_file);
 void                   thunar_job_operation_commit       (ThunarJobOperation    *job_operation);
 void                   thunar_job_operation_undo         (void);
 
+G_END_DECLS
+
 #endif /* __THUNAR_JOB_OPERATION_H__ */
diff --git a/thunar/thunar-job.c b/thunar/thunar-job.c
index 95b455ffc6a1789d05c033748b398a5cd4c96ab1..2d94cea0d6b7e4b910f76ab7525ad8cc7ccb5ad0 100644
--- a/thunar/thunar-job.c
+++ b/thunar/thunar-job.c
@@ -66,15 +66,16 @@ static ThunarJobResponse thunar_job_real_ask_replace    (ThunarJob          *job
 
 struct _ThunarJobPrivate
 {
-  ThunarJobResponse earlier_ask_create_response;
-  ThunarJobResponse earlier_ask_overwrite_response;
-  ThunarJobResponse earlier_ask_delete_response;
-  ThunarJobResponse earlier_ask_skip_response;
-  GList            *total_files;
-  guint             n_total_files;
-  gboolean          pausable;
-  gboolean          paused; /* the job has been manually paused using the UI */
-  gboolean          frozen; /* the job has been automaticaly paused regarding some parallel copy behavior */
+  ThunarJobResponse         earlier_ask_create_response;
+  ThunarJobResponse         earlier_ask_overwrite_response;
+  ThunarJobResponse         earlier_ask_delete_response;
+  ThunarJobResponse         earlier_ask_skip_response;
+  GList                    *total_files;
+  guint                     n_total_files;
+  gboolean                  pausable;
+  gboolean                  paused; /* the job has been manually paused using the UI */
+  gboolean                  frozen; /* the job has been automaticaly paused regarding some parallel copy behavior */
+  ThunarOperationLogMode    log_mode;
 };
 
 
@@ -804,3 +805,20 @@ thunar_job_processing_file (ThunarJob *job,
   if (G_LIKELY (job->priv->n_total_files > 0))
     exo_job_percent (EXO_JOB (job), (n_processed * 100.0) / job->priv->n_total_files);
 }
+
+
+
+void
+thunar_job_set_log_mode (ThunarJob             *job,
+                         ThunarOperationLogMode log_mode)
+{
+  job->priv->log_mode = log_mode;
+}
+
+
+
+ThunarOperationLogMode
+thunar_job_get_log_mode (ThunarJob *job)
+{
+  return job->priv->log_mode;
+}
diff --git a/thunar/thunar-job.h b/thunar/thunar-job.h
index 925218d41d4346e06b040831d1daef406714bb6a..36f8e54c980b9d77e52f34fa23b561993d4743a9 100644
--- a/thunar/thunar-job.h
+++ b/thunar/thunar-job.h
@@ -28,6 +28,7 @@
 
 #include <thunar/thunar-enum-types.h>
 #include <thunar/thunar-file.h>
+#include <thunar/thunar-job-operation.h>
 
 G_BEGIN_DECLS
 
@@ -104,6 +105,10 @@ gboolean          thunar_job_files_ready            (ThunarJob       *job,
                                                      GList           *file_list);
 void              thunar_job_new_files              (ThunarJob       *job,
                                                      const GList     *file_list);
+
+void                    thunar_job_set_log_mode     (ThunarJob              *job,
+                                                     ThunarOperationLogMode  log_mode);
+ThunarOperationLogMode  thunar_job_get_log_mode     (ThunarJob *job);
 G_END_DECLS
 
 #endif /* !__THUNAR_JOB_H__ */
diff --git a/thunar/thunar-menu.c b/thunar/thunar-menu.c
index 15df5b1f166811c8f31e8badd4b0344a2c14c78d..650147b509bb85cca37f2ed890c9c05d1cd3a5e9 100644
--- a/thunar/thunar-menu.c
+++ b/thunar/thunar-menu.c
@@ -252,6 +252,14 @@ thunar_menu_add_sections (ThunarMenu         *menu,
 
   _thunar_return_val_if_fail (THUNAR_IS_MENU (menu), FALSE);
 
+  if (menu_sections & THUNAR_MENU_SECTION_UNDO)
+    {
+      item_added = (thunar_action_manager_append_menu_item (menu->action_mgr, GTK_MENU_SHELL (menu), THUNAR_ACTION_MANAGER_ACTION_UNDO, force) != NULL);
+
+      if (item_added)
+        xfce_gtk_menu_append_separator (GTK_MENU_SHELL (menu));
+    }
+
   if (menu_sections & THUNAR_MENU_SECTION_CREATE_NEW_FILES)
     {
       item_added = FALSE;
@@ -363,14 +371,6 @@ thunar_menu_add_sections (ThunarMenu         *menu,
         }
     }
 
-  if (menu_sections & THUNAR_MENU_SECTION_UNDO)
-    {
-      item_added = (thunar_action_manager_append_menu_item (menu->action_mgr, GTK_MENU_SHELL (menu), THUNAR_ACTION_MANAGER_ACTION_UNDO, force) != NULL);
-
-      if (item_added)
-        xfce_gtk_menu_append_separator (GTK_MENU_SHELL (menu));
-    }
-
   if (menu_sections & THUNAR_MENU_SECTION_PROPERTIES)
       thunar_action_manager_append_menu_item (menu->action_mgr, GTK_MENU_SHELL (menu), THUNAR_ACTION_MANAGER_ACTION_PROPERTIES, FALSE);
 
diff --git a/thunar/thunar-transfer-job.c b/thunar/thunar-transfer-job.c
index d0987dd9be8c2dadfe0263177657962020d3209e..f0e9db6f623cce168d2bc8ecd06756f64a8a2899 100644
--- a/thunar/thunar-transfer-job.c
+++ b/thunar/thunar-transfer-job.c
@@ -470,7 +470,7 @@ ttj_copy_file (ThunarTransferJob  *job,
   gboolean   target_exists;
   gboolean   use_partial;
   gboolean   verify_file;
-  gboolean   add_to_operation;
+  gboolean   add_to_operation = TRUE;
   GError    *err = NULL;
 
   _thunar_return_val_if_fail (THUNAR_IS_TRANSFER_JOB (job), FALSE);
@@ -527,12 +527,6 @@ ttj_copy_file (ThunarTransferJob  *job,
                       exo_job_get_cancellable (EXO_JOB (job)),
                       thunar_transfer_job_progress, job, &err);
 
-  /* unless the copy involved an overwrite, register the operation*/
-  if (copy_flags & G_FILE_COPY_OVERWRITE)
-    add_to_operation = FALSE;
-  else
-    add_to_operation = TRUE;
-
   switch (job->transfer_verify_file)
     {
     case THUNAR_VERIFY_FILE_MODE_REMOTE_ONLY:
@@ -652,7 +646,12 @@ ttj_copy_file (ThunarTransferJob  *job,
   else
     {
       if (add_to_operation)
-        thunar_job_operation_add (operation, source_file, target_file);
+        {
+          if (copy_flags & G_FILE_COPY_OVERWRITE)
+            thunar_job_operation_overwrite (operation, target_file);
+
+          thunar_job_operation_add (operation, source_file, target_file);
+        }
       return TRUE;
     }
 }
@@ -1232,6 +1231,7 @@ thunar_transfer_job_prepare_untrash_file (ExoJob     *job,
 
 static gboolean
 thunar_transfer_job_move_file_with_rename (ExoJob             *job,
+                                           ThunarJobOperation *operation,
                                            ThunarTransferNode *node,
                                            GList              *tp,
                                            GFileCopyFlags      flags,
@@ -1263,6 +1263,10 @@ thunar_transfer_job_move_file_with_rename (ExoJob             *job,
       if (!move_rename_successful && !exo_job_is_cancelled (job) && ((*error)->code == G_IO_ERROR_EXISTS))
         continue;
 
+      /* Log the operation if the move and rename were successful and logging is enabled */
+      if (thunar_job_get_log_mode (THUNAR_JOB (job)) == THUNAR_OPERATION_LOG_OPERATIONS)
+        thunar_job_operation_add (operation, node->source_file, renamed_file);
+
       return move_rename_successful;
     }
 }
@@ -1270,6 +1274,7 @@ thunar_transfer_job_move_file_with_rename (ExoJob             *job,
 
 static gboolean
 thunar_transfer_job_move_file (ExoJob                *job,
+                               ThunarJobOperation    *operation,
                                GFileInfo             *info,
                                GList                 *sp,
                                ThunarTransferNode    *node,
@@ -1307,11 +1312,18 @@ thunar_transfer_job_move_file (ExoJob                *job,
                                          move_flags | G_FILE_COPY_OVERWRITE,
                                          exo_job_get_cancellable (job),
                                          NULL, NULL, error);
+
+          if (move_successful && thunar_job_get_log_mode (THUNAR_JOB (job)) == THUNAR_OPERATION_LOG_OPERATIONS)
+            {
+              thunar_job_operation_overwrite (operation, tp->data);
+              thunar_job_operation_add (operation, node->source_file, tp->data);
+            }
+
         }
       /* if the user chose to rename then try to do so */
       else if (response == THUNAR_JOB_RESPONSE_RENAME)
         {
-          move_successful = thunar_transfer_job_move_file_with_rename (job, node, tp, move_flags, error);
+          move_successful = thunar_transfer_job_move_file_with_rename (job, operation, node, tp, move_flags, error);
         }
       /* if the user chose to cancel then abort all remaining file moves */
       else if (response == THUNAR_JOB_RESPONSE_CANCEL)
@@ -1328,6 +1340,12 @@ thunar_transfer_job_move_file (ExoJob                *job,
        * files will be released and the matching list items will be dropped below
        */
     }
+  else
+    {
+      if (thunar_job_get_log_mode (THUNAR_JOB (job)) == THUNAR_OPERATION_LOG_OPERATIONS)
+        thunar_job_operation_add (operation, node->source_file, tp->data);
+    }
+
   if (*error == NULL)
     {
       if (move_successful)
@@ -1569,7 +1587,7 @@ thunar_transfer_job_execute (ExoJob  *job,
   ThunarTransferNode   *node;
   ThunarApplication    *application;
   ThunarTransferJob    *transfer_job = THUNAR_TRANSFER_JOB (job);
-  ThunarJobOperation   *operation;
+  ThunarJobOperation   *operation = NULL;
   GFileInfo            *info;
   GError               *err = NULL;
   GList                *new_files_list = NULL;
@@ -1577,6 +1595,7 @@ thunar_transfer_job_execute (ExoJob  *job,
   GList                *sp;
   GList                *tnext;
   GList                *tp;
+  gboolean              log_operations;
 
   _thunar_return_val_if_fail (THUNAR_IS_TRANSFER_JOB (job), FALSE);
   _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE);
@@ -1591,6 +1610,15 @@ thunar_transfer_job_execute (ExoJob  *job,
   thumbnail_cache = thunar_application_get_thumbnail_cache (application);
   g_object_unref (application);
 
+  /* whether or not we want to log operations to the undo list */
+  if (thunar_job_get_log_mode (THUNAR_JOB (transfer_job)) == THUNAR_OPERATION_LOG_OPERATIONS)
+    log_operations = TRUE;
+  else
+    log_operations = FALSE;
+
+  if (log_operations && transfer_job->type == THUNAR_TRANSFER_JOB_MOVE)
+    operation = thunar_job_operation_new (THUNAR_JOB_OPERATION_KIND_MOVE);
+
   for (sp = transfer_job->source_node_list, tp = transfer_job->target_file_list;
        sp != NULL && tp != NULL && err == NULL;
        sp = snext, tp = tnext)
@@ -1619,14 +1647,14 @@ thunar_transfer_job_execute (ExoJob  *job,
         {
           if (!thunar_transfer_job_prepare_untrash_file (job, info, tp->data, &err))
             break;
-          if (!thunar_transfer_job_move_file (job, info, sp, node, tp,
+          if (!thunar_transfer_job_move_file (job, operation, info, sp, node, tp,
                                               G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA,
                                               thumbnail_cache, &new_files_list, &err))
             break;
         }
       else if (transfer_job->type == THUNAR_TRANSFER_JOB_MOVE)
         {
-          if (!thunar_transfer_job_move_file (job, info, sp, node, tp,
+          if (!thunar_transfer_job_move_file (job, operation, info, sp, node, tp,
                                               G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_NO_FALLBACK_FOR_MOVE | G_FILE_COPY_ALL_METADATA,
                                               thumbnail_cache, &new_files_list, &err))
             break;
@@ -1663,7 +1691,9 @@ thunar_transfer_job_execute (ExoJob  *job,
 
       /* transfer starts now */
       transfer_job->start_time = g_get_real_time ();
-      operation = thunar_job_operation_new (THUNAR_JOB_OPERATION_KIND_COPY);
+
+      if (log_operations && transfer_job->type == THUNAR_TRANSFER_JOB_COPY)
+        operation = thunar_job_operation_new (THUNAR_JOB_OPERATION_KIND_COPY);
 
       /* perform the copy recursively for all source transfer nodes */
       for (sp = transfer_job->source_node_list, tp = transfer_job->target_file_list;
@@ -1686,8 +1716,13 @@ thunar_transfer_job_execute (ExoJob  *job,
       thunar_job_new_files (THUNAR_JOB (job), new_files_list);
       thunar_g_list_free_full (new_files_list);
 
-      thunar_job_operation_commit (operation);
-      g_object_unref (operation);
+      /* Note that we only created a new thunar job operation of the appropriate kind (move or copy)
+       * in a mutually exclusive way, so we know that only one operation was created. */
+      if (log_operations)
+        {
+          thunar_job_operation_commit (operation);
+          g_object_unref (operation);
+        }
 
       return TRUE;
     }