diff --git a/product/ERP5/ERP5Site.py b/product/ERP5/ERP5Site.py
index 690f05c6ac74d595f510d379435920d1935dd1a3..fd2a1b615f68c4a33d8cce9e918135e704577ea9 100644
--- a/product/ERP5/ERP5Site.py
+++ b/product/ERP5/ERP5Site.py
@@ -348,7 +348,7 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
       except AttributeError:
         reset_portal_type = False
 
-      synchronizeDynamicModules(self, force=reset_portal_type)
+      synchronizeDynamicModules(self, force=True)
     return self
 
   def manage_beforeDelete(self, item, container):
diff --git a/product/ERP5Type/Tool/ComponentTool.py b/product/ERP5Type/Tool/ComponentTool.py
index 6f1c0cd0e830207605bb332915cc0ae959626691..97ef9603bb8ab25224cebc18477b7e14795f6333 100644
--- a/product/ERP5Type/Tool/ComponentTool.py
+++ b/product/ERP5Type/Tool/ComponentTool.py
@@ -44,9 +44,9 @@ from zLOG import LOG, INFO, WARNING
 last_sync = -1
 class ComponentTool(BaseTool):
   """
-  This tool provides methods to load the the different types of
-  components of the ERP5 framework: Document classes, interfaces,
-  mixin classes, fields, accessors, etc.
+  This tool provides methods to load the the different types of components of
+  the ERP5 framework: Document classes, interfaces, mixin classes, fields,
+  accessors, etc.
   """
   id = "portal_components"
   meta_type = "ERP5 Component Tool"
@@ -55,22 +55,6 @@ class ComponentTool(BaseTool):
   security = ClassSecurityInfo()
   security.declareObjectProtected(Permissions.AccessContentsInformation)
 
-  def _resetModule(self, module):
-    for name, klass in module.__dict__.items():
-      if not (name[0] != '_' and isinstance(klass, ModuleType)):
-        continue
-
-      full_module_name = "%s.%s" % (module.__name__, name)
-
-      LOG("ERP5Type.Tool.ComponentTool", INFO, "Resetting " + full_module_name)
-
-      if name.endswith('_version'):
-        self._resetModule(getattr(module, name))
-
-      # The module must be deleted first
-      del sys.modules[full_module_name]
-      delattr(module, name)
-
   security.declareProtected(Permissions.ResetDynamicClasses, 'reset')
   def reset(self, force=True, reset_portal_type=True):
     """
@@ -103,16 +87,15 @@ class ComponentTool(BaseTool):
 
     with Base.aq_method_lock:
       for content_type in allowed_content_type_list:
-        module_name = content_type.split(' ')[0].lower()
+        package_name = content_type.split(' ')[0].lower()
 
         try:
-          module = getattr(erp5.component, module_name)
+          package = getattr(erp5.component, package_name)
         # XXX-arnau: not everything is defined yet...
         except AttributeError:
           pass
         else:
-          module._resetRegistry()
-          self._resetModule(module)
+          package.reset()
 
     if reset_portal_type:
       type_tool.resetDynamicDocumentsOnceAtTransactionBoundary()
diff --git a/product/ERP5Type/dynamic/component_package.py b/product/ERP5Type/dynamic/component_package.py
index ddee651e2955d3d02163cedef452e95a854732d6..b8fadafd87364db6c4766bde5509a07bb1eb2581 100644
--- a/product/ERP5Type/dynamic/component_package.py
+++ b/product/ERP5Type/dynamic/component_package.py
@@ -35,7 +35,7 @@ import threading
 
 from Products.ERP5.ERP5Site import getSite
 from types import ModuleType
-from zLOG import LOG, INFO
+from zLOG import LOG, INFO, BLATHER
 
 class ComponentVersionPackage(ModuleType):
   """
@@ -123,9 +123,6 @@ class ComponentDynamicPackage(ModuleType):
 
     return self.__registry_dict
 
-  def _resetRegistry(self):
-    self.__registry_dict.clear()
-
   def find_module(self, fullname, path=None):
     # Ignore imports with a path which are filesystem-only and any
     # absolute imports which does not start with this package prefix,
@@ -264,3 +261,32 @@ class ComponentDynamicPackage(ModuleType):
         setattr(self, component_name, new_module)
 
       return new_module
+
+  def reset(self, sub_package=None):
+    """
+    Reset the content of the current package and its version package as well
+    recursively. This method must be called within a lock to avoid side
+    effects
+    """
+    if sub_package is None:
+      # Clear the Component registry
+      self.__registry_dict.clear()
+      package = self
+    else:
+      package = sub_package
+
+    for name, module in package.__dict__.items():
+      if name[0] == '_' or not isinstance(module, ModuleType):
+        continue
+
+      # Reset the content of the version package before resetting it
+      elif isinstance(module, ComponentVersionPackage):
+        self.reset(sub_package=module)
+
+      module_name = "%s.%s" % (package.__name__, name)
+      LOG("ERP5Type.Tool.ComponentTool", BLATHER, "Resetting " + module_name)
+
+      # The module must be deleted first from sys.modules to avoid imports in
+      # the meantime
+      del sys.modules[module_name]
+      delattr(package, name)
diff --git a/product/ERP5Type/mixin/component.py b/product/ERP5Type/mixin/component.py
index c7894a53d0d037b732b7eec14c5e784d13cd2f09..bd3afa2e3921095e79a0474b730883aea5a3239f 100644
--- a/product/ERP5Type/mixin/component.py
+++ b/product/ERP5Type/mixin/component.py
@@ -150,7 +150,7 @@ class ComponentMixin(PropertyRecordableMixin, Base):
 
   _message_reference_not_set = "Reference must be set"
   _message_invalid_reference = "Reference cannot end with '_version' or "\
-      "start with '_' or be equal to find_module or load_module"
+      "start with '_' or be equal to find_module, load_module or reset"
 
   _message_version_not_set = "Version must be set"
   _message_invalid_version = "Version cannot start with '_'"
@@ -177,7 +177,7 @@ class ComponentMixin(PropertyRecordableMixin, Base):
 
     elif (reference.endswith('_version') or
           reference[0] == '_' or
-          reference in ('find_module', 'load_module')):
+          reference in ('find_module', 'load_module', 'reset')):
       error_list.append(
         ConsistencyMessage(self,
                            object_relative_url,