diff --git a/Control/xAODRootAccess/CMakeLists.txt b/Control/xAODRootAccess/CMakeLists.txt
index efa20e467e6aacfdf4d72a24294a66998fae8ffc..2c916d4e7a76c1bedd99a525ec5eb3b65718fac3 100644
--- a/Control/xAODRootAccess/CMakeLists.txt
+++ b/Control/xAODRootAccess/CMakeLists.txt
@@ -1,4 +1,4 @@
-# $Id: CMakeLists.txt 793319 2017-01-21 16:21:46Z ssnyder $
+# $Id: CMakeLists.txt 793778 2017-01-25 04:06:29Z ssnyder $
 #
 # Build configuration for the xAODRootAccess package.
 #
@@ -17,6 +17,7 @@ endif()
 # The dependencies of the package:
 atlas_depends_on_subdirs(
    PUBLIC
+   Control/CxxUtils
    Control/AthContainersInterfaces
    Control/AthContainers
    Event/xAOD/xAODCore
@@ -68,7 +69,7 @@ macro( _add_test name )
    atlas_add_test( ${name}
       SOURCES test/${name}.cxx
       INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
-      LINK_LIBRARIES ${ROOT_LIBRARIES} AthContainers xAODCore xAODRootAccess
+      LINK_LIBRARIES ${ROOT_LIBRARIES} CxxUtils AthContainers xAODCore xAODRootAccess
       PROPERTIES TIMEOUT 600 )
 endmacro( _add_test )
 
@@ -77,7 +78,9 @@ _add_test( ut_xaodrootaccess_metadata_test )
 _add_test( ut_xaodrootaccess_remap_test )
 _add_test( ut_xaodrootaccess_slimming_test )
 _add_test( ut_xaodrootaccess_stats_test )
+_add_test( ut_xaodrootaccess_tauxvector_test )
 _add_test( ut_xaodrootaccess_tauxstore_test )
+_add_test( ut_xaodrootaccess_tauxstore_insertmove_test )
 _add_test( ut_xaodrootaccess_tchain_test )
 _add_test( ut_xaodrootaccess_tevent_test )
 _add_test( ut_xaodrootaccess_tfileaccesstracer_test )
diff --git a/Control/xAODRootAccess/Root/TAuxStore.cxx b/Control/xAODRootAccess/Root/TAuxStore.cxx
index 1bd6baae11b3042c20b09c39986d6f16baa4a4f3..0e1ca3ad9eabde802e1255e72b8c68f390a4e66c 100644
--- a/Control/xAODRootAccess/Root/TAuxStore.cxx
+++ b/Control/xAODRootAccess/Root/TAuxStore.cxx
@@ -2,7 +2,7 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-// $Id: TAuxStore.cxx 793319 2017-01-21 16:21:46Z ssnyder $
+// $Id: TAuxStore.cxx 793778 2017-01-25 04:06:29Z ssnyder $
 
 // System include(s):
 #include <string.h>
@@ -637,6 +637,59 @@ namespace xAOD {
       return;
    }
 
+   bool TAuxStore::insertMove (size_t pos,
+                               IAuxStore& other,
+                               const SG::auxid_set_t& ignore_in)
+   {
+      // Guard against multi-threaded execution:
+      guard_t guard( m_mutex1 );
+
+      // A sanity check:
+      if( m_structMode == kObjectStore ) {
+         ::Error( "xAOD::TAuxStore::insertMove",
+                  XAOD_MESSAGE( "Should not have been called for single-object "
+                                "store" ) );
+         return false;
+      }
+
+      const SG::AuxTypeRegistry& r = SG::AuxTypeRegistry::instance();
+      bool nomove = true;
+      size_t other_size = other.size();
+
+      SG::auxid_set_t ignore = ignore_in;
+
+      for (SG::auxid_t id : m_auxIDs) {
+        SG::IAuxTypeVector* v_dst = nullptr;
+        if (id < m_vecs.size())
+          v_dst = m_vecs[id];
+        if (v_dst) {
+          ignore.insert (id);
+          if (other.getData (id)) {
+            void* src_ptr = other.getData (id, other_size, other_size);
+            if (src_ptr) {
+              if (!v_dst->insertMove (pos, src_ptr,
+                                      reinterpret_cast<char*>(src_ptr) + other_size*r.getEltSize(id)))
+                nomove = false;
+            }
+          }
+          else {
+            const void* orig = v_dst->toPtr();
+            v_dst->shift (pos, other_size);
+            if (orig != v_dst->toPtr())
+              nomove = false;
+          }
+        }
+      }
+
+      if( m_transientStore ) {
+        if (!m_transientStore->insertMove( pos, other, ignore ))
+          nomove = false;
+      }
+
+      return nomove;
+   }
+
+
    const void* TAuxStore::getIOData( auxid_t auxid ) const {
 
       // Guard against multi-threaded execution:
diff --git a/Control/xAODRootAccess/Root/TAuxVector.cxx b/Control/xAODRootAccess/Root/TAuxVector.cxx
index 0f1fafff19de9d1552f7fc080315c5640876d350..2d799c6b66a3cb80e41550882f152c172a999cbb 100644
--- a/Control/xAODRootAccess/Root/TAuxVector.cxx
+++ b/Control/xAODRootAccess/Root/TAuxVector.cxx
@@ -2,7 +2,7 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-// $Id: TAuxVector.cxx 793319 2017-01-21 16:21:46Z ssnyder $
+// $Id: TAuxVector.cxx 793778 2017-01-25 04:06:29Z ssnyder $
 
 // ROOT include(s):
 #include <TClass.h>
@@ -188,6 +188,27 @@ namespace xAOD {
       return;
    }
 
+   bool TAuxVector::insertMove (size_t pos, void* beg, void* end)
+   {
+     TVirtualCollectionProxy::TPushPop bind (m_proxy, m_vec);
+     size_t eltsz = m_proxy->GetIncrement();
+     const void* orig = this->toPtr();
+
+     char* begp = reinterpret_cast<char*> (beg);
+     char* endp = reinterpret_cast<char*> (end);
+     size_t nelt = (endp-begp) / eltsz;
+
+     shift (pos, nelt);
+     // FIXME: want move, not copy.
+     // But i don't seem to be able to call move operations through cling,
+     // so just use copy for now.
+     copyRange (beg,
+                reinterpret_cast<char*>(this->toPtr()) + pos*eltsz,
+                nelt);
+     return this->toPtr() == orig;
+   }
+
+
    void TAuxVector::copyRange( const void* src, void* dst, size_t n ) {
 
       // Size of an element in the vector:
diff --git a/Control/xAODRootAccess/test/ut_xaodrootaccess_tauxstore_insertmove_test.cxx b/Control/xAODRootAccess/test/ut_xaodrootaccess_tauxstore_insertmove_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4f2f2683acb41f25a84c8bdd78a5d8e114e20004
--- /dev/null
+++ b/Control/xAODRootAccess/test/ut_xaodrootaccess_tauxstore_insertmove_test.cxx
@@ -0,0 +1,168 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file xAODRootAccess/test/ut_xaodrootaccess_tauxstore_insertmove_test.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Jan, 2017
+ * @brief Unit tests TAuxStore::insertMove.
+ */
+
+
+#undef NDEBUG
+#include "xAODRootAccess/TAuxStore.h"
+#include "xAODRootAccess/tools/ReturnCheck.h"
+#include "AthContainers/AuxTypeRegistry.h"
+#include "AthContainers/AuxStoreInternal.h"
+#include "TTree.h"
+#include <iostream>
+#include <sstream>
+#include <cassert>
+
+
+const char* APP_NAME = "ut_xaodrootaccess_tauxstore_insertmove_test";
+
+
+struct MoveTest
+{
+  MoveTest(int x=0) : m_v(x) {}
+  MoveTest(const MoveTest& other): m_v (other.m_v) {}
+  MoveTest(MoveTest&& other): m_v (std::move(other.m_v)) {}
+  MoveTest& operator= (const MoveTest& other) {
+    if (this != &other) m_v = other.m_v;
+    return *this;
+  }
+  MoveTest& operator= (MoveTest&& other) {
+    if (this != &other) m_v = std::move(other.m_v);
+    return *this;
+  }
+  std::vector<int> m_v;
+  bool operator== (const MoveTest& other) const { return m_v.size() == other.m_v.size(); }
+};
+
+
+bool wasMoved (const MoveTest& x) { return x.m_v.empty(); }
+
+
+int test1()
+{
+  std::cout << "test1\n";
+
+  SG::auxid_t ityp1 = SG::AuxTypeRegistry::instance().getAuxID<int> ("anInt");
+  SG::auxid_t ityp2 = SG::AuxTypeRegistry::instance().getAuxID<int> ("anotherInt");
+  SG::auxid_t ityp3 = SG::AuxTypeRegistry::instance().getAuxID<int> ("anInt3");
+  SG::auxid_t ityp4 = SG::AuxTypeRegistry::instance().getAuxID<int> ("anInt4");
+  SG::auxid_t mtyp1 = SG::AuxTypeRegistry::instance().getAuxID<MoveTest> ("moveTest");
+
+  TTree tree ("t", "t");
+  xAOD::TAuxStore s1( "fooAux." );
+  RETURN_CHECK( APP_NAME, s1.readFrom (&tree) );
+  s1.resize(5);
+
+  int* i1 = reinterpret_cast<int*> (s1.getData(ityp1, 5, 20));
+  int* i2 = reinterpret_cast<int*> (s1.getData(ityp2, 5, 20));
+  MoveTest* m1 = reinterpret_cast<MoveTest*> (s1.getData(mtyp1, 5, 20));
+
+  for (int i=0; i<5; i++) {
+    i1[i] = i;
+    i2[i] = i+100;
+    m1[i] = MoveTest(i);
+  }
+
+  SG::AuxStoreInternal s2;
+  s2.resize(5);
+
+  int* i1_2 = reinterpret_cast<int*> (s2.getData(ityp1, 5, 5));
+  int* i3_2 = reinterpret_cast<int*> (s2.getData(ityp3, 5, 5));
+  int* i4_2 = reinterpret_cast<int*> (s2.getData(ityp4, 5, 5));
+  MoveTest* m1_2 = reinterpret_cast<MoveTest*> (s2.getData(mtyp1, 5, 5));
+  for (int i=0; i<5; i++) {
+    i1_2[i] = i+10;
+    i3_2[i] = i+110;
+    i4_2[i] = i+210;
+    m1_2[i] = MoveTest(i+10);
+  }
+
+  SG::auxid_set_t ignore { ityp4 };
+
+  s1.insertMove (3, s2, ignore);
+  assert (s1.size() == 10);
+  s1.reserve(20);
+  assert (s1.getData(ityp4) == nullptr);
+  const int* i3 = reinterpret_cast<const int*> (s1.getData(ityp3));
+  assert (i3 != 0);
+  i1 = reinterpret_cast<int*> (s1.getData(ityp1, 5, 20));
+  i2 = reinterpret_cast<int*> (s1.getData(ityp2, 5, 20));
+  m1 = reinterpret_cast<MoveTest*> (s1.getData(mtyp1, 5, 20));
+  for (int i=0; i<3; i++) {
+    assert (i1[i] == i);
+    assert (i2[i] == i+100);
+    assert (i3[i] == 0);
+    assert (m1[i] == MoveTest(i));
+  }
+  for (int i=0; i<5; i++) {
+    assert (i1[3+i] == i+10);
+    assert (i2[3+i] == 0);
+    assert (i3[3+i] == i+110);
+    assert (m1[3+i] == MoveTest(i+10));
+  }
+  for (int i=3; i<5; i++) {
+    assert (i1[5+i] == i);
+    assert (i2[5+i] == i+100);
+    assert (i3[5+i] == 0);
+    assert (m1[5+i] == MoveTest(i));
+  }
+  for (int i=0; i<5; i++) {
+    assert (wasMoved (m1_2[i]));
+  }
+
+  for (int i=0; i<5; i++) {
+    i1_2[i] = i+20;
+    i3_2[i] = i+120;
+    m1_2[i] = MoveTest(i+20);
+  }
+  s1.insertMove (10, s2, ignore);
+  assert (s1.size() == 15);
+  i1 = reinterpret_cast<int*> (s1.getData(ityp1, 5, 20));
+  i2 = reinterpret_cast<int*> (s1.getData(ityp2, 5, 20));
+  i3 = reinterpret_cast<int*> (s1.getData(ityp3, 5, 20));
+  m1 = reinterpret_cast<MoveTest*> (s1.getData(mtyp1, 5, 20));
+  for (int i=0; i<3; i++) {
+    assert (i1[i] == i);
+    assert (i2[i] == i+100);
+    assert (i3[i] == 0);
+    assert (m1[i] == MoveTest(i));
+  }
+  for (int i=0; i<5; i++) {
+    assert (i1[3+i] == i+10);
+    assert (i2[3+i] == 0);
+    assert (i3[3+i] == i+110);
+    assert (m1[3+i] == MoveTest(i+10));
+  }
+  for (int i=3; i<5; i++) {
+    assert (i1[5+i] == i);
+    assert (i2[5+i] == i+100);
+    assert (i3[5+i] == 0);
+    assert (m1[5+i] == MoveTest(i));
+  }
+  for (int i=0; i<5; i++) {
+    assert (i1[10+i] == i+20);
+    assert (i2[10+i] == 0);
+    assert (i3[10+i] == i+120);
+    assert (m1[10+i] == MoveTest(i+20));
+  }
+  for (int i=0; i<5; i++) {
+    assert (wasMoved (m1_2[i]));
+  }
+
+  return 0;
+}
+
+
+int main()
+{
+  test1();
+  return 0;
+}
diff --git a/Control/xAODRootAccess/test/ut_xaodrootaccess_tauxvector_test.cxx b/Control/xAODRootAccess/test/ut_xaodrootaccess_tauxvector_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..18bccccce7808b18307b34ca144b7dd628ad702e
--- /dev/null
+++ b/Control/xAODRootAccess/test/ut_xaodrootaccess_tauxvector_test.cxx
@@ -0,0 +1,107 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file xAODRootAccess/test/ut_xaodrootaccess_tauxvector_test.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Jan, 2017
+ * @brief Unit tests for TAuxVector.  (sadly incomplete)
+ */
+
+
+#undef NDEBUG
+#include "xAODRootAccess/tools/TAuxVector.h"
+#include "xAODRootAccess/tools/TAuxVectorFactory.h"
+#include "CxxUtils/StrFormat.h"
+#include "TClass.h"
+#include <iostream>
+#include <sstream>
+#include <cassert>
+
+
+std::string str (int x)
+{
+  return CxxUtils::strformat ("%d", x);
+}
+
+
+// Test insertMove.
+void test1()
+{
+  std::cout << "test1\n";
+
+  TClass* cl_int = TClass::GetClass ("vector<int>");
+  xAOD::TAuxVectorFactory fac_int (cl_int);
+  xAOD::TAuxVector vec_int = xAOD::TAuxVector (&fac_int, cl_int, 5, 5);
+  int* ptr_int = reinterpret_cast<int*> (vec_int.toPtr());
+
+  for (int i=0; i < 5; i++)
+    ptr_int[i] = i;
+
+  std::vector<int> v2_int { 10, 11, 12, 13, 14 };
+  vec_int.insertMove (3, v2_int.data(), v2_int.data() + 5);
+  assert (vec_int.size() == 10);
+  ptr_int = reinterpret_cast<int*> (vec_int.toPtr());
+  for (int i=0; i < 3; i++)
+    assert (ptr_int[i] == i);
+  for (int i=0; i < 5; i++)
+    assert (ptr_int[3+i] == 10+i);
+  for (int i=3; i < 5; i++)
+    assert (ptr_int[5+i] == i);
+
+  std::vector<int> v3_int { 20, 21, 22, 23, 24 };
+  vec_int.insertMove (10, v3_int.data(), v3_int.data() + 5);
+  assert (vec_int.size() == 15);
+  ptr_int = reinterpret_cast<int*> (vec_int.toPtr());
+  for (int i=0; i < 3; i++)
+    assert (ptr_int[i] == i);
+  for (int i=0; i < 5; i++)
+    assert (ptr_int[3+i] == 10+i);
+  for (int i=3; i < 5; i++)
+    assert (ptr_int[5+i] == i);
+  for (int i=0; i < 5; i++)
+    assert (ptr_int[10+i] == 20+i);
+
+  //*********************************
+
+  TClass* cl_str = TClass::GetClass ("vector<std::string>");
+  xAOD::TAuxVectorFactory fac_str (cl_str);
+  xAOD::TAuxVector vec_str = xAOD::TAuxVector (&fac_str, cl_str, 5, 5);
+  std::string* ptr_str = reinterpret_cast<std::string*> (vec_str.toPtr());
+
+  for (int i=0; i < 5; i++)
+    ptr_str[i] = str(i);
+
+  std::vector<std::string> v2_str { str(10), str(11), str(12), str(13), str(14) };
+  vec_str.insertMove (3, v2_str.data(), v2_str.data() + 5);
+  assert (vec_str.size() == 10);
+  ptr_str = reinterpret_cast<std::string*> (vec_str.toPtr());
+  for (int i=0; i < 3; i++)
+    assert (ptr_str[i] == str(i));
+  for (int i=0; i < 5; i++)
+    assert (ptr_str[3+i] == str(10+i));
+  for (int i=3; i < 5; i++)
+    assert (ptr_str[5+i] == str(i));
+
+  std::vector<std::string> v3_str { str(20), str(21), str(22), str(23), str(24) };
+  vec_str.insertMove (10, v3_str.data(), v3_str.data() + 5);
+  assert (vec_str.size() == 15);
+  ptr_str = reinterpret_cast<std::string*> (vec_str.toPtr());
+  for (int i=0; i < 3; i++)
+    assert (ptr_str[i] == str(i));
+  for (int i=0; i < 5; i++)
+    assert (ptr_str[3+i] == str(10+i));
+  for (int i=3; i < 5; i++)
+    assert (ptr_str[5+i] == str(i));
+  for (int i=0; i < 5; i++)
+    assert (ptr_str[10+i] == str(20+i));
+}
+
+
+int main()
+{
+  test1();
+  return 0;
+}
diff --git a/Control/xAODRootAccess/xAODRootAccess/TAuxStore.h b/Control/xAODRootAccess/xAODRootAccess/TAuxStore.h
index 9bb13e7751ee939f032ac6f81da9d6895475ac6a..f520c01d5819ed5586b0c9ba7fa624e8f8a57161 100644
--- a/Control/xAODRootAccess/xAODRootAccess/TAuxStore.h
+++ b/Control/xAODRootAccess/xAODRootAccess/TAuxStore.h
@@ -4,7 +4,7 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-// $Id: TAuxStore.h 793319 2017-01-21 16:21:46Z ssnyder $
+// $Id: TAuxStore.h 793778 2017-01-25 04:06:29Z ssnyder $
 #ifndef XAODROOTACCESS_TAUXSTORE_H
 #define XAODROOTACCESS_TAUXSTORE_H
 
@@ -21,6 +21,8 @@
 // Local include(s):
 #include "xAODRootAccess/tools/TReturnCode.h"
 
+#include "Rtypes.h"
+
 // Forward declaration(s):
 class TTree;
 class TBranch;
@@ -43,8 +45,8 @@ namespace xAOD {
    ///
    /// @author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
    ///
-   /// $Revision: 793319 $
-   /// $Date: 2017-01-21 17:21:46 +0100 (Sat, 21 Jan 2017) $
+   /// $Revision: 793778 $
+   /// $Date: 2017-01-25 05:06:29 +0100 (Wed, 25 Jan 2017) $
    ///
    class TAuxStore : public SG::IAuxStore,
                      public SG::IAuxStoreIO {
@@ -147,6 +149,10 @@ namespace xAOD {
       virtual void reserve( size_t size );
       /// Shift the contents of the stored arrays
       virtual void shift( size_t pos, ptrdiff_t offs );
+      /// Insert contents of another store via move.
+      virtual bool insertMove (size_t pos,
+                               IAuxStore& other,
+                               const SG::auxid_set_t& ignore);
 
       /// @}
 
diff --git a/Control/xAODRootAccess/xAODRootAccess/tools/TAuxVector.h b/Control/xAODRootAccess/xAODRootAccess/tools/TAuxVector.h
index e16b6c8cc289e97a172714513ef8eaae5a8c0873..432829ff11705f36606846cfa567a0f2073e136c 100644
--- a/Control/xAODRootAccess/xAODRootAccess/tools/TAuxVector.h
+++ b/Control/xAODRootAccess/xAODRootAccess/tools/TAuxVector.h
@@ -4,12 +4,13 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-// $Id: TAuxVector.h 793319 2017-01-21 16:21:46Z ssnyder $
+// $Id: TAuxVector.h 793778 2017-01-25 04:06:29Z ssnyder $
 #ifndef XAODROOTACCESS_TOOLS_TAUXVECTOR_H
 #define XAODROOTACCESS_TOOLS_TAUXVECTOR_H
 
 // EDM include(s):
 #include "AthContainersInterfaces/IAuxTypeVector.h"
+#include "AthContainersInterfaces/IAuxTypeVectorFactory.h"
 
 // Forward declaration(s):
 class TClass;
@@ -31,8 +32,8 @@ namespace xAOD {
    /// @author Scott Snyder <Scott.Snyder@cern.ch>
    /// @author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
    ///
-   /// $Revision: 793319 $
-   /// $Date: 2017-01-21 17:21:46 +0100 (Sat, 21 Jan 2017) $
+   /// $Revision: 793778 $
+   /// $Date: 2017-01-25 05:06:29 +0100 (Wed, 25 Jan 2017) $
    ///
    class TAuxVector : public SG::IAuxTypeVector {
 
@@ -68,6 +69,8 @@ namespace xAOD {
       virtual void reserve( size_t sz );
       /// Shift the elements of the vector
       virtual void shift( size_t pos, ptrdiff_t offs );
+      /// Insert a range of elements via move.
+      virtual bool insertMove (size_t pos, void* beg, void* end) override;
 
       /// @}