diff --git a/Control/AthContainers/AthContainers/AuxStoreInternal.h b/Control/AthContainers/AthContainers/AuxStoreInternal.h
index 703fe0454cc00b0588bed006dbb1c11bf362348a..5116fc8b9830ef5d86a312171de257e2807db5f1 100644
--- a/Control/AthContainers/AthContainers/AuxStoreInternal.h
+++ b/Control/AthContainers/AthContainers/AuxStoreInternal.h
@@ -4,7 +4,7 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-// $Id: AuxStoreInternal.h 793253 2017-01-20 18:17:19Z ssnyder $
+// $Id: AuxStoreInternal.h 793732 2017-01-24 19:42:30Z ssnyder $
 /**
  * @file AthContainers/AuxStoreInternal.h
  * @author scott snyder <snyder@bnl.gov>
@@ -189,6 +189,30 @@ public:
   virtual void shift (size_t pos, ptrdiff_t offs) override;
 
 
+  /**
+   * @brief Move all elements from @c other to this store.
+   * @param pos The starting index of the insertion.
+   * @param other Store from which to do the move.
+   * @param ignore Set of variables that should not be added to the store.
+   *
+   * Let @c len be the size of @c other.  The store will be increased
+   * in size by @c len elements, with the elements at @c pos being
+   * copied to @c pos+len.  Then, for each auxiliary variable, the
+   * entire contents of that variable for @c other will be moved to
+   * this store at index @c pos.  This will be done via move semantics
+   * if possible; otherwise, it will be done with a copy.  Variables
+   * present in this store but not in @c other will have the corresponding
+   * elements default-initialized.  Variables in @c other but not in this
+   * store will be added unless they are in @c ignore.
+   *
+   * Returns true if it is known that none of the vectors' memory moved,
+   * false otherwise.
+   */
+  virtual bool insertMove (size_t pos,
+                           IAuxStore& other,
+                           const SG::auxid_set_t& ignore = SG::auxid_set_t()) override;
+
+
   /**
    * @brief Return a set of identifiers for existing data items
    *        in this store.
@@ -339,6 +363,12 @@ protected:
 
 
 private:
+  /// Implementation of getDataInternal; no locking.
+  virtual void* getDataInternal_noLock (SG::auxid_t auxid,
+                                        size_t size,
+                                        size_t capacity,
+                                        bool no_lock_check);
+
   /// Return the number of elements in the store; no locking.
   size_t size_noLock() const;
 
diff --git a/Control/AthContainers/AthContainers/DataVector.h b/Control/AthContainers/AthContainers/DataVector.h
index dd364463783fa16fbe300f306ceeb94dcfc221db..1709613f4f667c1f75f707fcfd7677730d797b72 100644
--- a/Control/AthContainers/AthContainers/DataVector.h
+++ b/Control/AthContainers/AthContainers/DataVector.h
@@ -4,7 +4,7 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-// $Id: DataVector.h 783592 2016-11-11 04:35:43Z ssnyder $
+// $Id: DataVector.h 794114 2017-01-26 22:01:53Z ssnyder $
 
 /**
  * @file  AthContainers/DataVector.h
@@ -906,9 +906,8 @@ public:
    * @param trackIndices The index tracking policy.
    * @param store An associated auxiliary data store.
    *
-   * By default, a @c DataVector will own its elements (and take ownership
-   * of the pointers passed to this constructor).
-   * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
+   * A @c DataVector constructed this way will *not* own its elements
+   * by default.  To change this, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
    */
   DataVector(std::initializer_list<value_type> l,
 	     SG::OwnershipPolicy ownPolicy = SG::VIEW_ELEMENTS,
@@ -1435,6 +1434,34 @@ public:
 #endif
 
 
+  /**
+   * @brief Insert the contents of another @c DataVector,
+   *        with auxiliary data copied via move semantics.
+   * @param position Iterator before which the new elements will be added.
+   * @param other The vector to add.
+   *
+   * The ownership mode of this vector must be the same as @c other;
+   * otherwise, an exception will be thrown.
+   *
+   * If both vectors are view vectors, then this is the same
+   * as <code> insert (position, other.begin(), other.end()) </code>.
+   *
+   * Otherwise, the elements from @c other will be inserted into this vector.
+   * This vector will take ownership of the elements, and the ownership
+   * mode of @c other will be changed to @c VIEW_ELEMENTS.
+   * Auxiliary data for these elements will be transferred,
+   * using move semantics if possible.  (Thus, the auxiliary store
+   * for @c other may be modified and must not be locked.)
+   * Finally, the auxiliary store pointer for @c other will be cleared
+   * (but the store itself will not be deleted since it's not owned
+   * by the vector).
+   *
+   * Note: this method may only be called using the most derived
+   * @c DataVector in the hierarchy.
+   */
+  void insertMove (iterator position, DataVector& other);
+
+
   //@}
   //========================================================================
   /** @name Erasure operations. */
@@ -2103,9 +2130,8 @@ public:
    * @param trackIndices The index tracking policy.
    * @param store An associated auxiliary data store.
    *
-   * By default, a @c DataVector will own its elements (and take ownership
-   * of the pointers passed to this constructor).
-   * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
+   * A @c DataVector constructed this way will *not* own its elements
+   * by default.  To change this, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
    */
   DataVector(std::initializer_list<value_type> l,
 	     SG::OwnershipPolicy ownPolicy = SG::VIEW_ELEMENTS,
@@ -2652,6 +2678,34 @@ public:
 #endif
 
 
+  /**
+   * @brief Insert the contents of another @c DataVector,
+   *        with auxiliary data copied via move semantics.
+   * @param position Iterator before which the new elements will be added.
+   * @param other The vector to add.
+   *
+   * The ownership mode of this vector must be the same as @c other;
+   * otherwise, an exception will be thrown.
+   *
+   * If both vectors are view vectors, then this is the same
+   * as <code> insert (position, other.begin(), other.end()) </code>.
+   *
+   * Otherwise, the elements from @c other will be inserted into this vector.
+   * This vector will take ownership of the elements, and the ownership
+   * mode of @c other will be changed to @c VIEW_ELEMENTS.
+   * Auxiliary data for these elements will be transferred,
+   * using move semantics if possible.  (Thus, the auxiliary store
+   * for @c other may be modified and must not be locked.)
+   * Finally, the auxiliary store pointer for @c other will be cleared
+   * (but the store itself will not be deleted since it's not owned
+   * by the vector).
+   *
+   * Note: this method may only be called using the most derived
+   * @c DataVector in the hierarchy.
+   */
+  void insertMove (iterator position, DataVector& other);
+
+
   //@}
   //========================================================================
   /** @name Erasure operations. */
diff --git a/Control/AthContainers/AthContainers/DataVector.icc b/Control/AthContainers/AthContainers/DataVector.icc
index 90580eb8d38a49b1ec2c294e908c74660b38c5ef..f6becbb78fef6cab3e3d32a5872724b6b040cfd0 100644
--- a/Control/AthContainers/AthContainers/DataVector.icc
+++ b/Control/AthContainers/AthContainers/DataVector.icc
@@ -4,7 +4,7 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-// $Id: DataVector.icc 793303 2017-01-21 04:48:16Z ssnyder $
+// $Id: DataVector.icc 794114 2017-01-26 22:01:53Z ssnyder $
 /**
  * @file  AthContainers/DataVector.icc
  * @author scott snyder, Paolo Calafiura, etc
@@ -515,9 +515,9 @@ DataVector<T, BASE>::DataVector
  * @param trackIndices The index tracking policy.
  * @param store An associated auxiliary data store.
  *
- * By default, a @c DataVector will own its elements (and take ownership
- * of the pointers passed to this constructor).
- * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
+ *
+ * A @c DataVector constructed this way will *not* own its elements
+ * by default.  To change this, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
  *
  * Note that we do the complete initialization here in the derived class,
  * using the default constructors for the base classes.  The reason
@@ -1296,6 +1296,65 @@ void DataVector<T, BASE>::insert(iterator position,
 #endif
 
 
+/**
+ * @brief Insert the contents of another @c DataVector,
+ *        with auxiliary data copied via move semantics.
+ * @param position Iterator before which the new elements will be added.
+ * @param other The vector to add.
+ *
+ * The ownership mode of this vector must be the same as @c other;
+ * otherwise, an exception will be thrown.
+ *
+ * If both vectors are view vectors, then this is the same
+ * as <code> insert (position, other.begin(), other.end()) </code>.
+ *
+ * Otherwise, the elements from @c other will be inserted into this vector.
+ * This vector will take ownership of the elements, and the ownership
+ * mode of @c other will be changed to @c VIEW_ELEMENTS.
+ * Auxiliary data for these elements will be transferred,
+ * using move semantics if possible.  (Thus, the auxiliary store
+ * for @c other may be modified and must not be locked.)
+ * Finally, the auxiliary store pointer for @c other will be cleared
+ * (but the store itself will not be deleted since it's not owned
+ * by the vector).
+ *
+ * Note: this method may only be called using the most derived
+ * @c DataVector in the hierarchy.
+ */
+template <class T, class BASE>
+void
+DataVector<T, BASE>::insertMove (iterator position, DataVector& other)
+{
+  if (this->m_ownPolicy != other.ownPolicy())
+    throw SG::ExcInsertMoveOwnershipMismatch();
+
+  if (this->m_ownPolicy == SG::VIEW_ELEMENTS) {
+    this->insert (position, other.begin(), other.end());
+    return;
+  }
+
+  testInsert ("insertMove");
+  size_t pos = position.base() - this->m_pCont.begin();
+  this->m_pCont.insert (position.base(), other.begin(), other.end());
+  this->setIndices (this->begin()+pos, this->end(), pos);
+  other.m_ownPolicy = SG::VIEW_ELEMENTS;
+
+  SG::IAuxStore* otherStore = other.getStore();
+  if (otherStore) {
+    SG::IAuxStore* store = this->getStore();
+    if (store) {
+      if (!store->insertMove (pos, *otherStore))
+        this->clearCache();
+    }
+    else if (this->hasStore())
+      throw SG::ExcConstAuxData ("insertMove");
+    other.setStore (static_cast<SG::IAuxStore*>(nullptr));
+  }
+  else if (other.hasStore())
+    throw SG::ExcConstAuxData ("insertMove");
+}
+
+
 //=== Erasure operations.
 
 
@@ -2108,9 +2167,9 @@ DATAVECTOR::DataVector
  * @param trackIndices The index tracking policy.
  * @param store An associated auxiliary data store.
  *
- * By default, a @c DataVector will own its elements (and take ownership
- * of the pointers passed to this constructor).
- * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
+ *
+ * A @c DataVector constructed this way will *not* own its elements
+ * by default.  To change this, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
  */
 template <class T>
 inline
@@ -2953,6 +3012,65 @@ DATAVECTOR::insert (iterator position, std::initializer_list<value_type> l)
 #endif
 
 
+/**
+ * @brief Insert the contents of another @c DataVector,
+ *        with auxiliary data copied via move semantics.
+ * @param position Iterator before which the new elements will be added.
+ * @param other The vector to add.
+ *
+ * The ownership mode of this vector must be the same as @c other;
+ * otherwise, an exception will be thrown.
+ *
+ * If both vectors are view vectors, then this is the same
+ * as <code> insert (position, other.begin(), other.end()) </code>.
+ *
+ * Otherwise, the elements from @c other will be inserted into this vector.
+ * This vector will take ownership of the elements, and the ownership
+ * mode of @c other will be changed to @c VIEW_ELEMENTS.
+ * Auxiliary data for these elements will be transferred,
+ * using move semantics if possible.  (Thus, the auxiliary store
+ * for @c other may be modified and must not be locked.)
+ * Finally, the auxiliary store pointer for @c other will be cleared
+ * (but the store itself will not be deleted since it's not owned
+ * by the vector).
+ *
+ * Note: this method may only be called using the most derived
+ * @c DataVector in the hierarchy.
+ */
+template <class T>
+void
+DATAVECTOR::insertMove (iterator position, DataVector& other)
+{
+  if (this->m_ownPolicy != other.ownPolicy())
+    throw SG::ExcInsertMoveOwnershipMismatch();
+
+  if (this->m_ownPolicy == SG::VIEW_ELEMENTS) {
+    this->insert (position, other.begin(), other.end());
+    return;
+  }
+
+  testInsert ("insertMove");
+  size_t pos = position.base() - this->m_pCont.begin();
+  this->m_pCont.insert (position.base(), other.begin(), other.end());
+  this->setIndices (this->begin()+pos, this->end(), pos);
+  other.m_ownPolicy = SG::VIEW_ELEMENTS;
+
+  SG::IAuxStore* otherStore = other.getStore();
+  if (otherStore) {
+    SG::IAuxStore* store = this->getStore();
+    if (store) {
+      if (!store->insertMove (pos, *otherStore))
+        this->clearCache();
+    }
+    else if (this->hasStore())
+      throw SG::ExcConstAuxData ("insertMove");
+    other.setStore (static_cast<SG::IAuxStore*>(nullptr));
+  }
+  else if (other.hasStore())
+    throw SG::ExcConstAuxData ("insertMove");
+}
+
+
 //=== Erasure operations.
 
 
diff --git a/Control/AthContainers/AthContainers/exceptions.h b/Control/AthContainers/AthContainers/exceptions.h
index f3f6c126b2f8634bf57d3e8290a183d32900255f..6a512d4e811e188531fc72e3c6779471da8b356d 100644
--- a/Control/AthContainers/AthContainers/exceptions.h
+++ b/Control/AthContainers/AthContainers/exceptions.h
@@ -4,7 +4,7 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-// $Id: exceptions.h 721712 2016-02-03 20:57:28Z ssnyder $
+// $Id: exceptions.h 794114 2017-01-26 22:01:53Z ssnyder $
 /**
  * @file AthContainers/exceptions.h
  * @author scott snyder <snyder@bnl.gov>
@@ -349,6 +349,22 @@ public:
 void throwExcMissingBaseInfo (const std::type_info& ti);
 
 
+/**
+ * @brief Exception --- Ownership mismatch for insertMove.
+ *
+ * For insertMove, both vectors must have the same ownership mode.
+ */
+class ExcInsertMoveOwnershipMismatch
+  : public std::runtime_error
+{
+public:
+  /**
+   * @brief Constructor.
+   */
+  ExcInsertMoveOwnershipMismatch();
+};
+
+
 } // namespace SG
 
 
diff --git a/Control/AthContainers/AthContainers/tools/AuxTypeVector.h b/Control/AthContainers/AthContainers/tools/AuxTypeVector.h
index 4c11e80f68a4dc95b267ec0cb24af8de6c4671aa..54454981e7343ce7a95bc35d26a8d8baaa1fe18d 100644
--- a/Control/AthContainers/AthContainers/tools/AuxTypeVector.h
+++ b/Control/AthContainers/AthContainers/tools/AuxTypeVector.h
@@ -201,6 +201,29 @@ public:
    */
   virtual void shift (size_t pos, ptrdiff_t offs) override;
 
+  
+  /**
+   * @brief Insert elements into the vector via move semantics.
+   * @param pos The starting index of the insertion.
+   * @param beg Start of the range of elements to insert.
+   * @param end End of the range of elements to insert.
+   *
+   * @c beg and @c end define a range of container elements, with length
+   * @c len defined by the difference of the pointers divided by the
+   * element size.
+   *
+   * The size of the container will be increased by @c len, with the elements
+   * starting at @c pos copied to @c pos+len.
+   *
+   * The contents of the @c beg:end range will then be moved to our vector
+   * starting at @c pos.  This will be done via move semantics if possible;
+   * otherwise, it will be done with a copy.
+   *
+   * Returns true if it is known that the vector's memory did not move,
+   * false otherwise.
+   */
+  virtual bool insertMove (size_t pos, void* beg, void* end) override;
+
 
   /**
    * @brief Try to convert this aux vector to a @c PackedContainer.
@@ -249,6 +272,33 @@ public:
 
 
 private:
+  /**
+   * @brief Helper for @c insertMove.
+   * @param pos The starting index of the insertion.
+   * @param beg Start of the range of elements to insert.
+   * @param end End of the range of elements to insert.
+   *
+   * This does the actual move for POD types.
+   */
+  void insertMove1 (typename CONT::iterator pos,
+                    element_type* beg,
+                    element_type* end,
+                    std::true_type);
+
+
+  /**
+   * @brief Helper for @c insertMove.
+   * @param pos The starting index of the insertion.
+   * @param beg Start of the range of elements to insert.
+   * @param end End of the range of elements to insert.
+   *
+   * This does the actual move for non-POD types.
+   */
+  void insertMove1 (typename CONT::iterator pos,
+                    element_type* beg,
+                    element_type* end,
+                    std::false_type);
+
   /// The contained vector.
   vector_type* m_vecPtr;
 
diff --git a/Control/AthContainers/AthContainers/tools/AuxTypeVector.icc b/Control/AthContainers/AthContainers/tools/AuxTypeVector.icc
index 2b01eb102c1a3f115c898da4db1b180750a9c9de..379b855edb1698169cdad04bbda6a48120a8d98f 100644
--- a/Control/AthContainers/AthContainers/tools/AuxTypeVector.icc
+++ b/Control/AthContainers/AthContainers/tools/AuxTypeVector.icc
@@ -180,7 +180,7 @@ template <class T, class CONT>
 inline
 size_t AuxTypeVectorHolder<T, CONT>::size () const
 {
-  return m_vecPtr->size();
+  return m_vecPtr->size() / SCALE;
 }
 
 
@@ -309,6 +309,79 @@ void AuxTypeVectorHolder<T, CONT>::shift (size_t pos, ptrdiff_t offs)
 }
 
 
+/**
+ * @brief Helper for @c insertMove.
+ * @param pos The starting index of the insertion.
+ * @param beg Start of the range of elements to insert.
+ * @param end End of the range of elements to insert.
+ *
+ * This does the actual move for POD types.
+ */
+template <class T, class CONT>
+void AuxTypeVectorHolder<T, CONT>::insertMove1
+  (typename CONT::iterator pos,
+   element_type* beg,
+   element_type* end,
+   std::true_type)
+{
+  m_vecPtr->insert (pos, beg, end);
+}
+
+
+/**
+ * @brief Helper for @c insertMove.
+ * @param pos The starting index of the insertion.
+ * @param beg Start of the range of elements to insert.
+ * @param end End of the range of elements to insert.
+ *
+ * This does the actual move for non-POD types.
+ */
+template <class T, class CONT>
+void AuxTypeVectorHolder<T, CONT>::insertMove1
+  (typename CONT::iterator pos,
+   element_type* beg,
+   element_type* end,
+   std::false_type)
+{
+  // std::vector doesn't provide a way to insert a range via move.
+  // So first make space, then move.
+  typename CONT::iterator pos2= m_vecPtr->insert (pos, end-beg, element_type());
+  std::move (beg, end, pos2);
+}
+
+
+/**
+ * @brief Insert elements into the vector via move semantics.
+ * @param pos The starting index of the insertion.
+ * @param beg Start of the range of elements to insert.
+ * @param end End of the range of elements to insert.
+ *
+ * @c beg and @c end define a range of container elements, with length
+ * @c len defined by the difference of the pointers divided by the
+ * element size.
+ *
+ * The size of the container will be increased by @c len, with the elements
+ * starting at @c pos copied to @c pos+len.
+ *
+ * The contents of the @c beg:end range will then be moved to our vector
+ * starting at @c pos.  This will be done via move semantics if possible;
+ * otherwise, it will be done with a copy.
+ *
+ * Returns true if it is known that the vector's memory did not move,
+ * false otherwise.
+ */
+template <class T, class CONT>
+bool AuxTypeVectorHolder<T, CONT>::insertMove (size_t pos, void* beg, void* end)
+{
+  const void* orig = m_vecPtr->data();
+  insertMove1 (m_vecPtr->begin() + pos*SCALE,
+               reinterpret_cast<element_type*> (beg),
+               reinterpret_cast<element_type*> (end),
+               typename std::is_pod<element_type>::type());
+  return m_vecPtr->data() == orig;
+}
+
+
 } // namespace SG
 
 
diff --git a/Control/AthContainers/Root/AuxStoreInternal.cxx b/Control/AthContainers/Root/AuxStoreInternal.cxx
index de22e7e6e04b4808275e8a7db156f5b68c5967bf..6507ad0719890e95ba7ea61e10ca6adfd51d49b6 100644
--- a/Control/AthContainers/Root/AuxStoreInternal.cxx
+++ b/Control/AthContainers/Root/AuxStoreInternal.cxx
@@ -287,6 +287,79 @@ void AuxStoreInternal::shift (size_t pos, ptrdiff_t offs)
 }
 
 
+/**
+ * @brief Move all elements from @c other to this store.
+ * @param pos The starting index of the insertion.
+ * @param other Store from which to do the move.
+ * @param ignore Set of variables that should not be added to the store.
+ *
+ * Let @c len be the size of @c other.  The store will be increased
+ * in size by @c len elements, with the elements at @c pos being
+ * copied to @c pos+len.  Then, for each auxiliary variable, the
+ * entire contents of that variable for @c other will be moved to
+ * this store at index @c pos.  This will be done via move semantics
+ * if possible; otherwise, it will be done with a copy.  Variables
+ * present in this store but not in @c other will have the corresponding
+ * elements default-initialized.  Variables in @c other but not in this
+ * store will be added unless they are in @c ignore.
+ *
+ * Returns true if it is known that none of the vectors' memory moved,
+ * false otherwise.
+ */
+bool AuxStoreInternal::insertMove (size_t pos,
+                                   IAuxStore& other,
+                                   const SG::auxid_set_t& ignore)
+{
+  guard_t guard (m_mutex);
+  const AuxTypeRegistry& r = AuxTypeRegistry::instance();
+
+  if (m_locked)
+    throw ExcStoreLocked ("insertMove");
+  bool nomove = true;
+  size_t other_size = other.size();
+  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) {
+      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;
+      }
+    }
+  }
+
+  // Add any new variables not present in the original container.
+  for (SG::auxid_t id : other.getAuxIDs()) {
+    if (m_auxids.find(id) == m_auxids.end() &&
+        ignore.find(id) == ignore.end())
+    {
+      if (other.getData (id)) {
+        void* src_ptr = other.getData (id, other_size, other_size);
+        if (src_ptr) {
+          size_t sz = size_noLock();
+          (void)getDataInternal_noLock (id, sz, sz, false);
+          m_vecs[id]->resize (sz - other_size);
+          m_vecs[id]->insertMove (pos, src_ptr, reinterpret_cast<char*>(src_ptr) + other_size*r.getEltSize(id));
+          nomove = false;
+        }
+      }
+    }
+  }
+  
+  return nomove;
+}
+
+
 /**
  * @brief Return a set of identifiers for existing data items
  *        in this store.
@@ -522,6 +595,35 @@ void AuxStoreInternal::addAuxID (auxid_t auxid)
 }
 
 
+/// Implementation of getDataInternal; no locking.
+void* AuxStoreInternal::getDataInternal_noLock (auxid_t auxid,
+                                                size_t size,
+                                                size_t capacity,
+                                                bool no_lock_check)
+{
+  if (m_vecs.size() <= auxid) {
+    m_vecs.resize (auxid+1);
+    m_isDecoration.resize (auxid+1);
+  }
+  if (m_vecs[auxid] == 0) {
+    if (m_locked && !no_lock_check)
+      throw ExcStoreLocked (auxid);
+    m_vecs[auxid] = AuxTypeRegistry::instance().makeVector (auxid, size, capacity);
+    addAuxID (auxid);
+  }
+  else {
+    // Make sure the vector has at least the requested size.
+    // One way in which it could be short: setOption was called and created
+    // a variable in a store that had no other variables.
+    if (m_vecs[auxid]->size() < size) {
+      m_vecs[auxid]->resize (size);
+      m_vecs[auxid]->reserve (capacity);
+    }
+  }
+  return m_vecs[auxid]->toPtr();
+}
+
+
 /**
  * @brief Return the data vector for one aux data item
  * @param auxid The identifier of the desired aux data item.
@@ -545,26 +647,7 @@ void* AuxStoreInternal::getDataInternal (auxid_t auxid,
                                          bool no_lock_check)
 {
   guard_t guard (m_mutex);
-  if (m_vecs.size() <= auxid) {
-    m_vecs.resize (auxid+1);
-    m_isDecoration.resize (auxid+1);
-  }
-  if (m_vecs[auxid] == 0) {
-    if (m_locked && !no_lock_check)
-      throw ExcStoreLocked (auxid);
-    m_vecs[auxid] = AuxTypeRegistry::instance().makeVector (auxid, size, capacity);
-    addAuxID (auxid);
-  }
-  else {
-    // Make sure the vector has at least the requested size.
-    // One way in which it could be short: setOption was called and created
-    // a variable in a store that had no other variables.
-    if (m_vecs[auxid]->size() < size) {
-      m_vecs[auxid]->resize (size);
-      m_vecs[auxid]->reserve (capacity);
-    }
-  }
-  return m_vecs[auxid]->toPtr();
+  return getDataInternal_noLock (auxid, size, capacity, no_lock_check);
 }
 
 
diff --git a/Control/AthContainers/Root/exceptions.cxx b/Control/AthContainers/Root/exceptions.cxx
index 23be68db534434c03e1f41ef6a524a7562099bda..3bcf9a91d157aa92434c682e2e96c1076184f725 100644
--- a/Control/AthContainers/Root/exceptions.cxx
+++ b/Control/AthContainers/Root/exceptions.cxx
@@ -438,4 +438,16 @@ void throwExcMissingBaseInfo (const std::type_info& ti)
 }
 
 
+//*************************************************************************
+
+
+/**
+ * @brief Constructor.
+ */
+ExcInsertMoveOwnershipMismatch::ExcInsertMoveOwnershipMismatch()
+  : std::runtime_error ("Ownership mismatch for insertMove.")
+{
+}
+
+
 } // namespace SG
diff --git a/Control/AthContainers/share/AuxStoreInternal_test.ref b/Control/AthContainers/share/AuxStoreInternal_test.ref
index 8f6f54877d6a9042e565fcfca4af57599a71b942..4b991ef90d560c909f206aa94fc707b2fa163b54 100644
--- a/Control/AthContainers/share/AuxStoreInternal_test.ref
+++ b/Control/AthContainers/share/AuxStoreInternal_test.ref
@@ -2,4 +2,5 @@ test1
 test2
 test3
 test4
+test5
 test_threading
diff --git a/Control/AthContainers/share/DataVector_test.ref b/Control/AthContainers/share/DataVector_test.ref
index 32a375629a333a666a125631b4bc78071e639dc7..c58f991b8d697b3df93bdcc000e005e945d0d9b4 100755
--- a/Control/AthContainers/share/DataVector_test.ref
+++ b/Control/AthContainers/share/DataVector_test.ref
@@ -1,48 +1,48 @@
 *** DataVector_test test1 BEGIN ***
-intV: 0xf78a10 0xf789d0 0xf789f0 
+intV: 0x1052bf0 0x1052bb0 0x1052bd0 
 7 1 3 
-intV2: 0xf789b0 0xf78a60 0xf78a80 0xf78aa0 0xf78ae0 
+intV2: 0x1052b90 0x1052c40 0x1052c60 0x1052c80 0x104e890 
 5 5 5 5 6 
-dfluff: 0xf78b90 0xf78de0 
+dfluff: 0x10590b0 0x1059050 
  --> Now deleting copied vector, but it should not delete elements as it does not own them. You should not see message of Element Destructor
  <-- delete done
  --> Now deleting vector copied via iterator. You should NOT see the elements being deleted
  <-- delete done
  --> Now resizing DataVector<DerivedFluff>
  --> You should see one DerivedFluff object being deleted
- ----> Destructor of AbsFluff called for 0xf78de0. After return, left alive 1
+ ----> Destructor of AbsFluff called for 0x1059050. After return, left alive 1
  <-- resize done
  --> Now deleting DataVector<DerivedFluff>. You should see all remaining DerivedFluff objects being deleted
- ----> Destructor of AbsFluff called for 0xf78b90. After return, left alive 0
+ ----> Destructor of AbsFluff called for 0x10590b0. After return, left alive 0
  <-- delete done
  --> Now erasing one element of the DerivedFluff container. You should see one instance being deleted
- ----> Destructor of AbsFluff called for 0xf78b90. After return, left alive 3
+ ----> Destructor of AbsFluff called for 0x10590b0. After return, left alive 3
  <-- erase done
  --> Now resizing view container. You should NOT see the elements being deleted
  <-- resize done
  --> Now deleting two DerivedFluff instances
- ----> Destructor of AbsFluff called for 0xf79330. After return, left alive 14
- ----> Destructor of AbsFluff called for 0xf79690. After return, left alive 13
+ ----> Destructor of AbsFluff called for 0x1059860. After return, left alive 14
+ ----> Destructor of AbsFluff called for 0x1059bd0. After return, left alive 13
  <-- delete done
- ----> Destructor of AbsFluff called for 0xf79840. After return, left alive 17
- ----> Destructor of AbsFluff called for 0xf79620. After return, left alive 16
+ ----> Destructor of AbsFluff called for 0x1059d80. After return, left alive 17
+ ----> Destructor of AbsFluff called for 0x1059cc0. After return, left alive 16
 *** DataVector_test OK ***
- ----> Destructor of AbsFluff called for 0xf79690. After return, left alive 15
- ----> Destructor of AbsFluff called for 0xf79330. After return, left alive 14
- ----> Destructor of AbsFluff called for 0xf795f0. After return, left alive 13
- ----> Destructor of AbsFluff called for 0xf78b90. After return, left alive 12
- ----> Destructor of AbsFluff called for 0xf78f90. After return, left alive 11
- ----> Destructor of AbsFluff called for 0xf79000. After return, left alive 10
- ----> Destructor of AbsFluff called for 0xf790a0. After return, left alive 9
- ----> Destructor of AbsFluff called for 0xf79130. After return, left alive 8
- ----> Destructor of AbsFluff called for 0xf79070. After return, left alive 7
- ----> Destructor of AbsFluff called for 0xf791e0. After return, left alive 6
- ----> Destructor of AbsFluff called for 0xf79250. After return, left alive 5
- ----> Destructor of AbsFluff called for 0xf792c0. After return, left alive 4
- ----> Destructor of AbsFluff called for 0xf793c0. After return, left alive 3
- ----> Destructor of AbsFluff called for 0xf78de0. After return, left alive 2
- ----> Destructor of AbsFluff called for 0xf78cb0. After return, left alive 1
- ----> Destructor of AbsFluff called for 0xf78eb0. After return, left alive 0
+ ----> Destructor of AbsFluff called for 0x1059860. After return, left alive 15
+ ----> Destructor of AbsFluff called for 0x1059b40. After return, left alive 14
+ ----> Destructor of AbsFluff called for 0x1059c00. After return, left alive 13
+ ----> Destructor of AbsFluff called for 0x10590b0. After return, left alive 12
+ ----> Destructor of AbsFluff called for 0x1059390. After return, left alive 11
+ ----> Destructor of AbsFluff called for 0x1059420. After return, left alive 10
+ ----> Destructor of AbsFluff called for 0x10594e0. After return, left alive 9
+ ----> Destructor of AbsFluff called for 0x1059570. After return, left alive 8
+ ----> Destructor of AbsFluff called for 0x1059650. After return, left alive 7
+ ----> Destructor of AbsFluff called for 0x10596b0. After return, left alive 6
+ ----> Destructor of AbsFluff called for 0x1059740. After return, left alive 5
+ ----> Destructor of AbsFluff called for 0x10597d0. After return, left alive 4
+ ----> Destructor of AbsFluff called for 0x10598f0. After return, left alive 3
+ ----> Destructor of AbsFluff called for 0x1059050. After return, left alive 2
+ ----> Destructor of AbsFluff called for 0x1059110. After return, left alive 1
+ ----> Destructor of AbsFluff called for 0x10592a0. After return, left alive 0
 test2
 name: DataVector<AA>
  clid, vers, is_do: 2699 1 0
@@ -52,3 +52,4 @@ name: DataVector<CC>
  clid, vers, is_do: aa4491f 2 0
 test_auxdata
 test_emptysort
+test_insertmove
diff --git a/Control/AthContainers/share/exceptions_test.ref b/Control/AthContainers/share/exceptions_test.ref
index 7a6ae0ccb65d5aaf8386cedf22476d7bce30ff43..7e933c4db72f763f6ea992ce9e7f715afcefc2ed 100644
--- a/Control/AthContainers/share/exceptions_test.ref
+++ b/Control/AthContainers/share/exceptions_test.ref
@@ -20,3 +20,4 @@ SG::ExcUnknownAuxItem: Unknown aux data item bar::foo (of type int)
 SG::ExcDVToELV: Can't convert DataVector to vector of ElementLinks: why
 ViewVector not in view mode.
 ViewVector intwas used in a context that requires a CLID, but no CLID was available.  Make sure a VIEWVECTOR_CLASS_DEF declaration exists for the class in a library that has been loaded.
+Ownership mismatch for insertMove.
diff --git a/Control/AthContainers/test/AuxStoreInternal_test.cxx b/Control/AthContainers/test/AuxStoreInternal_test.cxx
index 97c483456e29f2ee741dde395133ebe0394e4a63..29a216e35dc806e436087a0014eee481994357df 100644
--- a/Control/AthContainers/test/AuxStoreInternal_test.cxx
+++ b/Control/AthContainers/test/AuxStoreInternal_test.cxx
@@ -31,6 +31,27 @@
 #include "auxid_set_equal.icc"
 
 
+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(); }
+
+
 class AuxStoreInternalTest
   : public SG::AuxStoreInternal
 {
@@ -304,6 +325,110 @@ void test4()
 }
 
 
+// Test insertMove
+void test5()
+{
+  std::cout << "test5\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");
+  SG::AuxStoreInternal s1;
+  s1.reserve(20);
+  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 };
+
+  assert (! s1.insertMove (3, s2, ignore)); // false due to added vbl
+  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);
+  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);
+  }
+  assert (s1.insertMove (10, s2, ignore));
+  assert (s1.size() == 15);
+  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]));
+  }
+}
+
+
 class ThreadingTest
 {
 public:
@@ -410,6 +535,7 @@ int main()
   test2();
   test3();
   test4();
+  test5();
   test_threading();
   return 0;
 }
diff --git a/Control/AthContainers/test/AuxTypeVector_test.cxx b/Control/AthContainers/test/AuxTypeVector_test.cxx
index 5b2c7e3adbf3eecd601c047ca67b0755c5638eed..6b4d7dfe7c59cdc58873a21fd0fc1b856f93d762 100644
--- a/Control/AthContainers/test/AuxTypeVector_test.cxx
+++ b/Control/AthContainers/test/AuxTypeVector_test.cxx
@@ -15,15 +15,43 @@
 
 
 #include "AthContainers/tools/AuxTypeVector.h"
+#include <vector>
 #include <iostream>
 #include <cassert>
 #include <memory>
 
 
 template <class T>
-T makeT(int x=0) { return T(x); }
+T makeT1(int x, T*) { return T(x); }
 
-bool makeT(int x=0) { return (x&1) != 0; }
+bool makeT1(int x, bool) { return (x&1) != 0; }
+
+template <class T>
+T makeT(int x=0) { return makeT1(x, static_cast<T*>(nullptr)); }
+
+
+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(); }
+};
+
+
+template <class T>
+bool wasMoved (const T&) { return true; }
+
+bool wasMoved (const MoveTest& x) { return x.m_v.empty(); }
 
 
 template <class T>
@@ -32,12 +60,12 @@ void test_vector1()
   SG::AuxTypeVector<T>* vconcrete = new SG::AuxTypeVector<T> (10, 20);
   SG::IAuxTypeVector* v = vconcrete;
   T* ptr = reinterpret_cast<T*> (v->toPtr());
-  ptr[0] = makeT(1);
-  ptr[1] = makeT(2);
+  ptr[0] = makeT<T>(1);
+  ptr[1] = makeT<T>(2);
   assert (v->size() == 10);
 
-  assert (vconcrete->vec()[0] == makeT(1));
-  assert (vconcrete->vec()[1] == makeT(2));
+  assert (vconcrete->vec()[0] == makeT<T>(1));
+  assert (vconcrete->vec()[1] == makeT<T>(2));
   assert (&vconcrete->vec() == v->toVector());
 
   v->reserve (50);
@@ -45,39 +73,39 @@ void test_vector1()
   assert (v->resize (40) == true);
   T* ptr2 = reinterpret_cast<T*> (v->toPtr());
   assert (ptr == ptr2);
-  assert (ptr[0] == makeT(1));
-  assert (ptr[1] == makeT(2));
+  assert (ptr[0] == makeT<T>(1));
+  assert (ptr[1] == makeT<T>(2));
   assert (v->size() == 40);
 
   v->shift (1, 1);
-  assert (ptr[0] == makeT(1));
-  assert (ptr[1] == makeT());
-  assert (ptr[2] == makeT(2));
+  assert (ptr[0] == makeT<T>(1));
+  assert (ptr[1] == makeT<T>());
+  assert (ptr[2] == makeT<T>(2));
 
-  ptr[1] = makeT(20);
+  ptr[1] = makeT<T>(20);
   v->shift (1, -1);
-  assert (ptr[0] == makeT(20));
-  assert (ptr[1] == makeT(2));
+  assert (ptr[0] == makeT<T>(20));
+  assert (ptr[1] == makeT<T>(2));
 
   SG::IAuxTypeVector* v2 = new SG::AuxTypeVector<T> (10, 20);
   ptr2 = reinterpret_cast<T*> (v2->toPtr());
   SG::AuxTypeVector<T>::copy (ptr2, 0, ptr, 1);
   SG::AuxTypeVector<T>::copy (ptr2, 1, ptr, 0);
-  assert (ptr2[0] == makeT(2));
-  assert (ptr2[1] == makeT(20));
+  assert (ptr2[0] == makeT<T>(2));
+  assert (ptr2[1] == makeT<T>(20));
 
-  ptr2[0] = makeT(10);
-  ptr2[1] = makeT(11);
+  ptr2[0] = makeT<T>(10);
+  ptr2[1] = makeT<T>(11);
 
   SG::AuxTypeVector<T>::swap (ptr2, 0, ptr, 1);
-  assert (ptr[0] == makeT(20));
-  assert (ptr[1] == makeT(10));
-  assert (ptr2[0] == makeT(2));
-  assert (ptr2[1] == makeT(11));
+  assert (ptr[0] == makeT<T>(20));
+  assert (ptr[1] == makeT<T>(10));
+  assert (ptr2[0] == makeT<T>(2));
+  assert (ptr2[1] == makeT<T>(11));
 
   SG::AuxTypeVector<T>::clear (ptr2, 0);
-  assert (ptr2[0] == makeT());
-  assert (ptr2[1] == makeT(11));
+  assert (ptr2[0] == makeT<T>());
+  assert (ptr2[1] == makeT<T>(11));
 
   SG::IAuxTypeVector* v3 = v->clone();
   assert (v3->size() == v->size());
@@ -108,47 +136,47 @@ void test_vector2()
 {
   SG::AuxTypeVector<T> v1 (10, 10);
   T* ptr1 = reinterpret_cast<T*> (v1.toPtr());
-  ptr1[0] = makeT(1);
-  ptr1[1] = makeT(2);
+  ptr1[0] = makeT<T>(1);
+  ptr1[1] = makeT<T>(2);
 
   SG::AuxTypeVector<T> v2 (v1);
   T* ptr2 = reinterpret_cast<T*> (v2.toPtr());
   assert (v1.size() == 10);
   assert (v2.size() == 10);
-  assert (ptr1[0] == makeT(1));
-  assert (ptr1[1] == makeT(2));
-  assert (ptr2[0] == makeT(1));
-  assert (ptr2[1] == makeT(2));
+  assert (ptr1[0] == makeT<T>(1));
+  assert (ptr1[1] == makeT<T>(2));
+  assert (ptr2[0] == makeT<T>(1));
+  assert (ptr2[1] == makeT<T>(2));
 
   SG::AuxTypeVector<T> v3 (0, 0);
   v3 = v1;
   T* ptr3 = reinterpret_cast<T*> (v3.toPtr());
   assert (v1.size() == 10);
   assert (v3.size() == 10);
-  assert (ptr1[0] == makeT(1));
-  assert (ptr1[1] == makeT(2));
-  assert (ptr3[0] == makeT(1));
-  assert (ptr3[1] == makeT(2));
+  assert (ptr1[0] == makeT<T>(1));
+  assert (ptr1[1] == makeT<T>(2));
+  assert (ptr3[0] == makeT<T>(1));
+  assert (ptr3[1] == makeT<T>(2));
 
   v3.resize (3);
-  ptr3[0] = makeT(3);
-  ptr3[1] = makeT(2);
-  ptr3[2] = makeT(1);
+  ptr3[0] = makeT<T>(3);
+  ptr3[1] = makeT<T>(2);
+  ptr3[2] = makeT<T>(1);
 
   SG::AuxTypeVector<T> v4 (std::move (v3));
   T* ptr4 = reinterpret_cast<T*> (v4.toPtr());
   assert (v4.size() == 3);
   assert (v3.size() == 0);
-  assert (ptr4[0] == makeT(3));
-  assert (ptr4[1] == makeT(2));
-  assert (ptr4[2] == makeT(1));
+  assert (ptr4[0] == makeT<T>(3));
+  assert (ptr4[1] == makeT<T>(2));
+  assert (ptr4[2] == makeT<T>(1));
 
   v3 = std::move(v4);
   assert (v3.size() == 3);
   assert (v4.size() == 0);
-  assert (ptr3[0] == makeT(3));
-  assert (ptr3[1] == makeT(2));
-  assert (ptr3[2] == makeT(1));
+  assert (ptr3[0] == makeT<T>(3));
+  assert (ptr3[1] == makeT<T>(2));
+  assert (ptr3[2] == makeT<T>(1));
 }
 
 
@@ -158,47 +186,98 @@ void test_vector3()
   typedef typename SG::AuxTypeVectorHolder<T>::vector_type vector_type;
 
   vector_type* vptr1 = new vector_type;
-  vptr1->push_back (makeT(1));
-  vptr1->push_back (makeT(2));
-  vptr1->push_back (makeT(3));
+  vptr1->push_back (makeT<T>(1));
+  vptr1->push_back (makeT<T>(2));
+  vptr1->push_back (makeT<T>(3));
 
   SG::AuxTypeVectorHolder<T> v1 (vptr1, true);
   assert (v1.size() == 3);
   T* ptr1 = reinterpret_cast<T*> (v1.toPtr());
-  assert (ptr1[0] == makeT(1));
-  assert (ptr1[1] == makeT(2));
-  assert (ptr1[2] == makeT(3));
+  assert (ptr1[0] == makeT<T>(1));
+  assert (ptr1[1] == makeT<T>(2));
+  assert (ptr1[2] == makeT<T>(3));
 
   SG::AuxTypeVectorHolder<T> v2 (v1);
   assert (v1.size() == 3);
   assert (v2.size() == 3);
   T* ptr2 = reinterpret_cast<T*> (v2.toPtr());
-  assert (ptr2[0] == makeT(1));
-  assert (ptr2[1] == makeT(2));
-  assert (ptr2[2] == makeT(3));
+  assert (ptr2[0] == makeT<T>(1));
+  assert (ptr2[1] == makeT<T>(2));
+  assert (ptr2[2] == makeT<T>(3));
 
   v2.resize(2);
-  ptr2[0] = makeT(2);
-  ptr2[1] = makeT(1);
+  ptr2[0] = makeT<T>(2);
+  ptr2[1] = makeT<T>(1);
   v1 = v2;
   assert (v1.size() == 2);
   assert (v2.size() == 2);
-  assert (ptr2[0] == makeT(2));
-  assert (ptr2[1] == makeT(1));
+  assert (ptr2[0] == makeT<T>(2));
+  assert (ptr2[1] == makeT<T>(1));
 
   SG::AuxTypeVectorHolder<T> v3 (std::move(v2));
   assert (v2.size() == 2);
   assert (v3.size() == 2);
   T* ptr3 = reinterpret_cast<T*> (v3.toPtr());
-  assert (ptr3[0] == makeT(2));
-  assert (ptr3[1] == makeT(1));
+  assert (ptr3[0] == makeT<T>(2));
+  assert (ptr3[1] == makeT<T>(1));
 
   v1 = std::move(v3);
   ptr1 = reinterpret_cast<T*> (v1.toPtr());
   assert (v1.size() == 2);
   assert (v3.size() == 2);
-  assert (ptr1[0] == makeT(2));
-  assert (ptr1[1] == makeT(1));
+  assert (ptr1[0] == makeT<T>(2));
+  assert (ptr1[1] == makeT<T>(1));
+}
+
+
+// Testing insertMove
+template <class T>
+void test_vector4 (bool isPOD)
+{
+  SG::AuxTypeVector<T> v1 (10, 20);
+  T* ptr1 = reinterpret_cast<T*> (v1.toPtr());
+  for (int i=0; i<10; i++)
+    ptr1[i] = makeT<T>(i);
+
+  SG::AuxTypeVector<T> v2 (5, 5);
+  T* ptr2 = reinterpret_cast<T*> (v2.toPtr());
+  for (int i=0; i<5; i++)
+    ptr2[i] = makeT<T>(i+10);
+
+  assert (v1.insertMove (3, ptr2, ptr2+5));
+  assert (v1.size() == 15);
+  for (int i=0; i<3; i++)
+    assert (ptr1[i] == makeT<T>(i));
+  for (int i=0; i<5; i++)
+    assert (ptr1[3+i] == makeT<T>(10+i));
+  for (int i=0; i<7; i++)
+    assert (ptr1[8+i] == makeT<T>(3+i));
+  assert (v2.size() == 5);
+  for (int i=0; i<5; i++)
+    assert (wasMoved (ptr2[i]));
+
+  for (int i=0; i<5; i++)
+    ptr2[i] = makeT<T>(i+20);
+  for (int i=0; i<5; i++)
+    assert (isPOD || !wasMoved (ptr2[i]));
+
+  assert (v1.insertMove (15, ptr2, ptr2+5));
+  assert (v1.size() == 20);
+  for (int i=0; i<3; i++)
+    assert (ptr1[i] == makeT<T>(i));
+  for (int i=0; i<5; i++)
+    assert (ptr1[3+i] == makeT<T>(10+i));
+  for (int i=0; i<7; i++)
+    assert (ptr1[8+i] == makeT<T>(3+i));
+  for (int i=0; i<5; i++)
+    assert (ptr1[15+i] == makeT<T>(20+i));
+  assert (v2.size() == 5);
+  for (int i=0; i<5; i++)
+    assert (wasMoved (ptr2[i]));
+
+  SG::AuxTypeVector<T> v3 (1000, 1000);
+  T* ptr3 = reinterpret_cast<T*> (v3.toPtr());
+  assert ( ! v1.insertMove (20, ptr3, ptr3 + v3.size()) );
 }
 
 
@@ -208,6 +287,7 @@ void test_vector()
   test_vector1<T>();
   test_vector2<T>();
   test_vector3<T>();
+  test_vector4<T>(true);
 }
 
 
@@ -217,6 +297,7 @@ void test1()
   test_vector<int>();
   test_vector<bool>();
   test_vector<float>();
+  test_vector4<MoveTest>(false);
 }
 
 
diff --git a/Control/AthContainers/test/AuxVectorData_test.cxx b/Control/AthContainers/test/AuxVectorData_test.cxx
index e27fefed0dd79af35e5236374870d4b2b0b45d89..289a896979360eda6cc0a8b0e6e50091547d6f6d 100644
--- a/Control/AthContainers/test/AuxVectorData_test.cxx
+++ b/Control/AthContainers/test/AuxVectorData_test.cxx
@@ -382,6 +382,7 @@ public:
   virtual bool resize (size_t) { std::abort(); }
   virtual void reserve (size_t) { std::abort(); }
   virtual void shift (size_t, ptrdiff_t) { std::abort(); }
+  virtual bool insertMove (size_t, IAuxStore&, const SG::auxid_set_t&) { std::abort(); }
 
   virtual bool setOption (SG::auxid_t auxid, const SG::AuxDataOption&  option)
   {
diff --git a/Control/AthContainers/test/DataVector_test.cxx b/Control/AthContainers/test/DataVector_test.cxx
index f74af5dd99c103aa3194bcfee7f2f3a5838ce854..20ebcdc51fcf4b592ef96349f8e7ae2d75b113e9 100644
--- a/Control/AthContainers/test/DataVector_test.cxx
+++ b/Control/AthContainers/test/DataVector_test.cxx
@@ -768,6 +768,7 @@ public:
   virtual bool resize (size_t) { return false; }
   virtual void reserve (size_t) { }
   virtual void shift (size_t, ptrdiff_t) { }
+  virtual bool insertMove (size_t, IAuxStore&, const SG::auxid_set_t&) { return false; }
 
   SG::auxid_set_t m_auxids;
 };
@@ -783,6 +784,90 @@ void test_emptysort()
 }
 
 
+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(); }
+};
+
+
+template <class T>
+bool wasMoved (const T&) { return true; }
+
+bool wasMoved (const MoveTest& x) { return x.m_v.empty(); }
+
+
+template <class T>
+void test_insertmove1()
+{
+  typename T::template Accessor<MoveTest> auxm ("auxm");
+
+  DataVector<T> v;
+  SG::AuxStoreInternal store;
+  v.setStore (&store);
+
+  for (int i=0; i < 5; i++)
+    v.push_back (new T(i));
+  for (int i=0; i < 5; i++) {
+    v[i]->setaux();
+    auxm(*v[i]) = MoveTest(i);
+  }
+
+  DataVector<T> v2;
+  SG::AuxStoreInternal store2;
+  v2.setStore (&store2);
+
+  for (int i=0; i < 5; i++)
+    v2.push_back (new T(i+10));
+  for (int i=0; i < 5; i++) {
+    v2[i]->setaux();
+    auxm(*v2[i]) = MoveTest(i+10);
+  }
+
+  v.insertMove (v.begin()+3, v2);
+  assert (v.size() == 10);
+  checkaux (v);
+  CHECK_INDICES (v);
+  for (int i=0; i < 3; i++) {
+    assert (v[i]->x == i);
+    assert (auxm(*v[i]) == MoveTest(i));
+  }
+  for (int i=0; i < 5; i++) {
+    assert (v[3+i]->x == i+10);
+    assert (auxm(*v[3+i]) == MoveTest(i+10));
+  }
+  for (int i=3; i < 5; i++) {
+    assert (v[5+i]->x == i);
+    assert (auxm(*v[5+i]) == MoveTest(i));
+  }
+  assert (v2.ownPolicy() == SG::VIEW_ELEMENTS);
+  assert (v2.size() == 5);
+  for (int i=0; i < 5; i++) {
+    assert (v2[i]->x == i+10);
+  }
+}
+
+
+void test_insertmove()
+{
+  std::cout << "test_insertmove\n";
+  test_insertmove1<AAux>();
+  test_insertmove1<BAux>();
+  test_insertmove1<CAux>();
+}
+
+
 int main()
 {
   test1();
@@ -793,6 +878,7 @@ int main()
   test_iterate();
   test_auxdata();
   test_emptysort();
+  test_insertmove();
   return 0;
 }
 
diff --git a/Control/AthContainers/test/DataVector_test.icc b/Control/AthContainers/test/DataVector_test.icc
index c15bb05c791cd0b0e7b9e97dbb6e07c47c05e02b..62956a44d62e9200670e3c4f773f9357082c8d89 100644
--- a/Control/AthContainers/test/DataVector_test.icc
+++ b/Control/AthContainers/test/DataVector_test.icc
@@ -3397,6 +3397,107 @@ void test2_insert_range()
 }
 
 
+// Test insertMove
+template <class DV>
+void test2_insertMove1()
+{
+  typedef typename DV::base_value_type T;
+  clear_dtor_log();
+  {
+    DV v;
+    v.push_back (new T(3));
+    v.push_back (new T(4));
+    DV v2 ({new T(1), new T(2)}, SG::OWN_ELEMENTS);
+    v.insertMove (v.begin()+1, v2);
+    myassert (v.size() == 4);
+    myassert (v[0]->x == 3);
+    myassert (v[1]->x == 1);
+    myassert (v[2]->x == 2);
+    myassert (v[3]->x == 4);
+    CHECK_INDICES(v);
+
+    myassert (v2.size() == 2);
+    myassert (v2.ownPolicy() == SG::VIEW_ELEMENTS);
+    myassert (v2[0]->x == 1);
+    myassert (v2[1]->x == 2);
+  }
+  check_dtor_log (3, 1, 2, 4);
+
+  {
+    DV v (SG::VIEW_ELEMENTS);
+    v.push_back (new T(3));
+    v.push_back (new T(4));
+    DV v2 ({new T(1), new T(2)}, SG::VIEW_ELEMENTS);
+    v.insertMove (v.end(), v2);
+    myassert (v.size() == 4);
+    myassert (v[0]->x == 3);
+    myassert (v[1]->x == 4);
+    myassert (v[2]->x == 1);
+    myassert (v[3]->x == 2);
+    CHECK_INDICES(v);
+
+    myassert (v2.size() == 2);
+    myassert (v2.ownPolicy() == SG::VIEW_ELEMENTS);
+    myassert (v2[0]->x == 1);
+    myassert (v2[1]->x == 2);
+  }
+  check_dtor_log();
+
+  {
+    DV v;
+    v.push_back (new T(3));
+    v.push_back (new T(4));
+    DV v2 ({new T(1), new T(2)}, SG::VIEW_ELEMENTS);
+    EXPECT_EXCEPTION (SG::ExcInsertMoveOwnershipMismatch,
+                      v.insertMove (v.begin()+1, v2));
+  }
+
+  clear_dtor_log();
+}
+template <class B, class D>
+void test2_insertMove()
+{
+  test2_insertMove1<DataVector<B> > ();
+  test2_insertMove1<DataVector<D> > ();
+  test2_insertMove1<DataVector<typename test2_maybeconst<D>::type> > ();
+  //test2_insertMove1<ConstDataVector<DataVector<D> > > ();
+
+  DataVector<D> vd;
+  SG::AuxStoreInternal store;
+  setaux (vd, store);
+  vd.push_back (make_comp<D>(3));
+  vd.push_back (make_comp<D>(4));
+  DataVector<B>& vb = vd;
+
+  DataVector<D> vd2;
+  SG::AuxStoreInternal store2;
+  setaux (vd2, store2);
+  vd2.push_back (make_comp<D>(1));
+  vd2.push_back (make_comp<D>(2));
+  EXPECT_EXCEPTION (SG::ExcInsertionInBaseClass,
+                    vb.insertMove (vb.begin()+1, vd2));
+
+  vd.insertMove (vd.begin()+1, vd2);
+  checkaux(vd);
+
+  DataVector<D> vd3;
+  SG::AuxStoreInternal store3;
+  setaux (vd3, store3);
+  vd3.push_back (make_comp<D>(5));
+  vd3.push_back (make_comp<D>(6));
+
+  vd.setStore (vd.getConstStore());
+  bool caught = false;
+  try {
+    vd.insertMove (vd.begin(), vd3);
+  }
+  catch (SG::ExcConstAuxData&) {
+    caught = true;
+  }
+  myassert (caught || !typename SG::AuxStore_traits<D>::flag());
+}
+
+
 // Test clear()
 template <class DV>
 void test2_clear1()
@@ -5994,6 +6095,7 @@ void do_test2()
   test2_operator_assign<B,D> ();
   test2_insert_value<B,D> ();
   test2_insert_range<B,D> ();
+  test2_insertMove<B,D> ();
   test2_clear<B,D> ();
   test2_swap<B,D> ();
   test2_assign<B,D> ();
diff --git a/Control/AthContainers/test/exceptions_test.cxx b/Control/AthContainers/test/exceptions_test.cxx
index 42bb1a1cc7c5148b948ece4b2ebe6387636855b2..94e95f241b18424d693fdd33fe418a3908ba3d5e 100644
--- a/Control/AthContainers/test/exceptions_test.cxx
+++ b/Control/AthContainers/test/exceptions_test.cxx
@@ -53,6 +53,7 @@ void test1()
   std::cout << SG::ExcDVToELV("why").what() << "\n";
   std::cout << SG::ExcViewVectorNotView().what() << "\n";
   std::cout << SG::ExcMissingViewVectorCLID(typeid(int)).what() << "\n";
+  std::cout << SG::ExcInsertMoveOwnershipMismatch().what() << "\n";
 }