diff --git a/git/__init__.py b/git/__init__.py
index 0514d545b..8c31e3094 100644
--- a/git/__init__.py
+++ b/git/__init__.py
@@ -49,7 +49,8 @@ def _init_externals():
     LockFile,
     BlockingLockFile,
     Stats,
-    Actor
+    Actor,
+    rmtree,
 )
 
 #} END imports
diff --git a/git/cmd.py b/git/cmd.py
index 245a7f609..112075057 100644
--- a/git/cmd.py
+++ b/git/cmd.py
@@ -822,27 +822,30 @@ def _call_process(self, method, *args, **kwargs):
             is realized as non-existent
 
         :param kwargs:
-            is a dict of keyword arguments.
-            This function accepts the same optional keyword arguments
-            as execute().
-
-        ``Examples``::
+            It contains key-values for the following:
+            - the :meth:`execute()` kwds, as listed in :var:`execute_kwargs`;
+            - "command options" to be converted by :meth:`transform_kwargs()`;
+            - the `'insert_kwargs_after'` key which its value must match one of ``*args``,
+              and any cmd-options will be appended after the matched arg.
+        
+        Examples::
+        
             git.rev_list('master', max_count=10, header=True)
+        
+        turns into::
+        
+           git rev-list max-count 10 --header master
 
         :return: Same as ``execute``"""
         # Handle optional arguments prior to calling transform_kwargs
         # otherwise these'll end up in args, which is bad.
-        _kwargs = dict()
-        for kwarg in execute_kwargs:
-            try:
-                _kwargs[kwarg] = kwargs.pop(kwarg)
-            except KeyError:
-                pass
+        exec_kwargs = dict((k, v) for k, v in kwargs.items() if k in execute_kwargs)
+        opts_kwargs = dict((k, v) for k, v in kwargs.items() if k not in execute_kwargs)
 
-        insert_after_this_arg = kwargs.pop('insert_kwargs_after', None)
+        insert_after_this_arg = opts_kwargs.pop('insert_kwargs_after', None)
 
         # Prepare the argument list
-        opt_args = self.transform_kwargs(**kwargs)
+        opt_args = self.transform_kwargs(**opts_kwargs)
         ext_args = self.__unpack_args([a for a in args if a is not None])
 
         if insert_after_this_arg is None:
@@ -851,11 +854,11 @@ def _call_process(self, method, *args, **kwargs):
             try:
                 index = ext_args.index(insert_after_this_arg)
             except ValueError:
-                raise ValueError("Couldn't find argument '%s' in args %s to insert kwargs after"
+                raise ValueError("Couldn't find argument '%s' in args %s to insert cmd options after"
                                  % (insert_after_this_arg, str(ext_args)))
             # end handle error
             args = ext_args[:index + 1] + opt_args + ext_args[index + 1:]
-        # end handle kwargs
+        # end handle opts_kwargs
 
         call = [self.GIT_PYTHON_GIT_EXECUTABLE]
 
@@ -870,7 +873,7 @@ def _call_process(self, method, *args, **kwargs):
         call.append(dashify(method))
         call.extend(args)
 
-        return self.execute(call, **_kwargs)
+        return self.execute(call, **exec_kwargs)
 
     def _parse_object_header(self, header_line):
         """
diff --git a/git/repo/base.py b/git/repo/base.py
index 0f85e3d96..a9f90a175 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -33,6 +33,8 @@
 import os.path as osp
 
 from .fun import rev_parse, is_git_dir, find_submodule_git_dir, touch
+import gc
+import gitdb
 
 
 log = logging.getLogger(__name__)
@@ -177,9 +179,21 @@ def __init__(self, path=None, odbt=DefaultDBType, search_parent_directories=Fals
             args.append(self.git)
         self.odb = odbt(*args)
 
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_value, traceback):
+        self.close()
+
     def __del__(self):
+        self.close()
+
+    def close(self):
         if self.git:
             self.git.clear_cache()
+            gc.collect()
+            gitdb.util.mman.collect()
+            gc.collect()
 
     def __eq__(self, rhs):
         if isinstance(rhs, Repo):
diff --git a/git/test/lib/helper.py b/git/test/lib/helper.py
index 743f720c8..c3960c248 100644
--- a/git/test/lib/helper.py
+++ b/git/test/lib/helper.py
@@ -7,18 +7,22 @@
 
 import contextlib
 from functools import wraps
-import sys
+import gc
 import io
 import logging
 import os
+import sys
 import tempfile
 import textwrap
 import time
 
 from git.compat import string_types, is_win
 from git.util import rmtree, cwd
+import gitdb
 
 import os.path as osp
+
+
 if sys.version_info[0:2] == (2, 6):
     import unittest2 as unittest
 else:
@@ -96,7 +100,6 @@ def wrapper(self):
             # a windows-only issue. In fact things should be deleted, as well as
             # memory maps closed, once objects go out of scope. For some reason
             # though this is not the case here unless we collect explicitly.
-            import gc
             gc.collect()
             if not keep:
                 rmtree(path)
@@ -144,9 +147,10 @@ def repo_creator(self):
                 os.chdir(prev_cwd)
                 rw_repo.git.clear_cache()
                 rw_repo = None
-                import gc
-                gc.collect()
                 if repo_dir is not None:
+                    gc.collect()
+                    gitdb.util.mman.collect()
+                    gc.collect()
                     rmtree(repo_dir)
                 # END rm test repo if possible
             # END cleanup
@@ -303,7 +307,8 @@ def remote_repo_creator(self):
                 rw_daemon_repo.git.clear_cache()
                 del rw_repo
                 del rw_daemon_repo
-                import gc
+                gc.collect()
+                gitdb.util.mman.collect()
                 gc.collect()
                 if rw_repo_dir:
                     rmtree(rw_repo_dir)
@@ -357,7 +362,6 @@ def setUpClass(cls):
         each test type has its own repository
         """
         from git import Repo
-        import gc
         gc.collect()
         cls.rorepo = Repo(GIT_REPO)