diff --git a/apps/openmw/mwgui/merchantrepair.cpp b/apps/openmw/mwgui/merchantrepair.cpp
index 49cc60d8a..0d1a57000 100644
--- a/apps/openmw/mwgui/merchantrepair.cpp
+++ b/apps/openmw/mwgui/merchantrepair.cpp
@@ -117,15 +117,18 @@ void MerchantRepair::exit()
 
 void MerchantRepair::onRepairButtonClick(MyGUI::Widget *sender)
 {
+    MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
+
     // repair
     MWWorld::Ptr item = *sender->getUserData<MWWorld::Ptr>();
     item.getCellRef().setCharge(item.getClass().getItemMaxHealth(item));
 
+    player.getClass().getContainerStore(player).restack(item);
+
     MWBase::Environment::get().getSoundManager()->playSound("Repair",1,1);
 
     int price = boost::lexical_cast<int>(sender->getUserString("Price"));
 
-    MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
     player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
 
     startRepair(mActor);
diff --git a/apps/openmw/mwgui/recharge.cpp b/apps/openmw/mwgui/recharge.cpp
index 079564273..9c43b1416 100644
--- a/apps/openmw/mwgui/recharge.cpp
+++ b/apps/openmw/mwgui/recharge.cpp
@@ -165,6 +165,8 @@ void Recharge::onItemClicked(MyGUI::Widget *sender)
         item.getCellRef().setEnchantmentCharge(
             std::min(item.getCellRef().getEnchantmentCharge() + restored, static_cast<float>(enchantment->mData.mCharge)));
 
+        player.getClass().getContainerStore(player).restack(item);
+
         player.getClass().skillUsageSucceeded (player, ESM::Skill::Enchant, 0);
     }
 
diff --git a/apps/openmw/mwmechanics/repair.cpp b/apps/openmw/mwmechanics/repair.cpp
index 9f2c851cf..6d6f889ed 100644
--- a/apps/openmw/mwmechanics/repair.cpp
+++ b/apps/openmw/mwmechanics/repair.cpp
@@ -57,10 +57,13 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair)
         charge = std::min(charge + y, itemToRepair.getClass().getItemMaxHealth(itemToRepair));
         itemToRepair.getCellRef().setCharge(charge);
 
+        // attempt to re-stack item, in case it was fully repaired
+        MWWorld::ContainerStoreIterator stacked = player.getClass().getContainerStore(player).restack(itemToRepair);
+
         // set the OnPCRepair variable on the item's script
-        std::string script = itemToRepair.getClass().getScript(itemToRepair);
+        std::string script = stacked->getClass().getScript(itemToRepair);
         if(script != "")
-            itemToRepair.getRefData().getLocals().setVarByInt(script, "onpcrepair", 1);
+            stacked->getRefData().getLocals().setVarByInt(script, "onpcrepair", 1);
 
         // increase skill
         player.getClass().skillUsageSucceeded(player, ESM::Skill::Armorer, 0);
diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp
index e330ddaee..18ebd82db 100644
--- a/apps/openmw/mwworld/containerstore.cpp
+++ b/apps/openmw/mwworld/containerstore.cpp
@@ -141,6 +141,34 @@ void MWWorld::ContainerStore::unstack(const Ptr &ptr, const Ptr& container)
     remove(ptr, ptr.getRefData().getCount()-1, container);
 }
 
+MWWorld::ContainerStoreIterator MWWorld::ContainerStore::restack(const MWWorld::Ptr& item)
+{
+    MWWorld::ContainerStoreIterator retval = end();
+    for (MWWorld::ContainerStoreIterator iter (begin()); iter != end(); ++iter)
+    {
+        if (item == *iter)
+        {
+            retval = iter;
+            break;
+        }
+    }
+
+    if (retval == end())
+        throw std::runtime_error("item is not from this container");
+
+    for (MWWorld::ContainerStoreIterator iter (begin()); iter != end(); ++iter)
+    {
+        if (stacks(*iter, item))
+        {
+            iter->getRefData().setCount(iter->getRefData().getCount() + item.getRefData().getCount());
+            item.getRefData().setCount(0);
+            retval = iter;
+            break;
+        }
+    }
+    return retval;
+}
+
 bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2)
 {
     const MWWorld::Class& cls1 = ptr1.getClass();
diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp
index 7c81bdb6e..6d9d7a6bb 100644
--- a/apps/openmw/mwworld/containerstore.hpp
+++ b/apps/openmw/mwworld/containerstore.hpp
@@ -134,6 +134,11 @@ namespace MWWorld
             void unstack (const Ptr& ptr, const Ptr& container);
             ///< Unstack an item in this container. The item's count will be set to 1, then a new stack will be added with (origCount-1).
 
+            MWWorld::ContainerStoreIterator restack (const MWWorld::Ptr& item);
+            ///< Attempt to re-stack an item in this container.
+            /// If a compatible stack is found, the item's count is added to that stack, then the original is deleted.
+            /// @return If the item was stacked, return the stack, otherwise return the old (untouched) item.
+
             /// @return How many items with refID \a id are in this container?
             int count (const std::string& id);
 
diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp
index 2eb8aeb46..891440023 100644
--- a/apps/openmw/mwworld/inventorystore.cpp
+++ b/apps/openmw/mwworld/inventorystore.cpp
@@ -512,28 +512,21 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipSlot(int slot, c
         // empty this slot
         mSlots[slot] = end();
 
-        // restack the previously equipped item with other (non-equipped) items
-        for (MWWorld::ContainerStoreIterator iter (begin()); iter != end(); ++iter)
+        if (it->getRefData().getCount())
         {
-            if (stacks(*iter, *it))
-            {
-                iter->getRefData().setCount(iter->getRefData().getCount() + it->getRefData().getCount());
-                it->getRefData().setCount(0);
-                retval = iter;
-                break;
-            }
-        }
+            retval = restack(*it);
 
-        if (actor.getRefData().getHandle() == "player")
-        {
-            // Unset OnPCEquip Variable on item's script, if it has a script with that variable declared
-            const std::string& script = it->getClass().getScript(*it);
-            if (script != "")
-                (*it).getRefData().getLocals().setVarByInt(script, "onpcequip", 0);
-
-            if ((mSelectedEnchantItem != end()) && (mSelectedEnchantItem == it))
+            if (actor.getRefData().getHandle() == "player")
             {
-                mSelectedEnchantItem = end();
+                // Unset OnPCEquip Variable on item's script, if it has a script with that variable declared
+                const std::string& script = it->getClass().getScript(*it);
+                if (script != "")
+                    (*it).getRefData().getLocals().setVarByInt(script, "onpcequip", 0);
+
+                if ((mSelectedEnchantItem != end()) && (mSelectedEnchantItem == it))
+                {
+                    mSelectedEnchantItem = end();
+                }
             }
         }
 
@@ -633,8 +626,15 @@ void MWWorld::InventoryStore::rechargeItems(float duration)
         static float fMagicItemRechargePerSecond = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
                     "fMagicItemRechargePerSecond")->getFloat();
 
-        it->first->getCellRef().setEnchantmentCharge(std::min (it->first->getCellRef().getEnchantmentCharge() + fMagicItemRechargePerSecond * duration,
-                                                              it->second));
+        if (it->first->getCellRef().getEnchantmentCharge() <= it->second)
+        {
+            it->first->getCellRef().setEnchantmentCharge(std::min (it->first->getCellRef().getEnchantmentCharge() + fMagicItemRechargePerSecond * duration,
+                                                                  it->second));
+
+            // attempt to restack when fully recharged
+            if (it->first->getCellRef().getEnchantmentCharge() == it->second)
+                it->first = restack(*it->first);
+        }
     }
 }