diff --git a/lib/bb/fetch2/git.py b/lib/bb/fetch2/git.py
index 52fffe21d..6d3bc3447 100644
--- a/lib/bb/fetch2/git.py
+++ b/lib/bb/fetch2/git.py
@@ -656,30 +656,37 @@ class Git(FetchMethod):
         # The url is local ud.clonedir, set it to upstream one
         runfetchcmd("%s remote set-url origin %s" % (ud.basecmd, shlex.quote(repourl)), d, workdir=dest)
 
-    def unpack(self, ud, destdir, d):
-        """ unpack the downloaded src to destdir"""
-
+    def destdir(self, ud, destdir, d):
         subdir = ud.parm.get("subdir")
         subpath = ud.parm.get("subpath")
-        readpathspec = ""
         def_destsuffix = (d.getVar("BB_GIT_DEFAULT_DESTSUFFIX") or "git") + "/"
 
         if subpath:
-            readpathspec = ":%s" % subpath
             def_destsuffix = "%s/" % os.path.basename(subpath.rstrip('/'))
 
         if subdir:
-            # If 'subdir' param exists, create a dir and use it as destination for unpack cmd
             if os.path.isabs(subdir):
-                if not os.path.realpath(subdir).startswith(os.path.realpath(destdir)):
-                    raise bb.fetch2.UnpackError("subdir argument isn't a subdirectory of unpack root %s" % destdir, ud.url)
                 destdir = subdir
             else:
                 destdir = os.path.join(destdir, subdir)
             def_destsuffix = ""
 
         destsuffix = ud.parm.get("destsuffix", def_destsuffix)
-        destdir = ud.destdir = os.path.join(destdir, destsuffix)
+        return os.path.join(destdir, destsuffix)
+
+    def unpack(self, ud, destdir, d):
+        """ unpack the downloaded src to destdir"""
+
+        subpath = ud.parm.get("subpath")
+        readpathspec = ""
+        if subpath:
+            readpathspec = ":%s" % subpath
+
+        root = destdir
+        destdir = self.destdir(ud, root, d)
+        if not os.path.realpath(destdir).startswith(os.path.realpath(root)):
+            raise bb.fetch2.UnpackError("subdir argument isn't a subdirectory of unpack root %s" % root, ud.url)
+
         if os.path.exists(destdir):
             bb.utils.prunedir(destdir)
         if not ud.bareclone:
diff --git a/lib/bb/fetch2/gitannex.py b/lib/bb/fetch2/gitannex.py
index 80a808d88..dbb74e35d 100644
--- a/lib/bb/fetch2/gitannex.py
+++ b/lib/bb/fetch2/gitannex.py
@@ -65,13 +65,15 @@ class GitANNEX(Git):
     def unpack(self, ud, destdir, d):
         Git.unpack(self, ud, destdir, d)
 
+        destdir = self.destdir(ud, destdir, d)
+
         try:
-            runfetchcmd("%s annex init" % (ud.basecmd), d, workdir=ud.destdir)
+            runfetchcmd("%s annex init" % (ud.basecmd), d, workdir=destdir)
         except bb.fetch.FetchError:
             pass
 
-        annex = self.uses_annex(ud, d, ud.destdir)
+        annex = self.uses_annex(ud, d, destdir)
         if annex:
-            runfetchcmd("%s annex get" % (ud.basecmd), d, workdir=ud.destdir)
-            runfetchcmd("chmod u+w -R %s/.git/annex" % (ud.destdir), d, quiet=True, workdir=ud.destdir)
+            runfetchcmd("%s annex get" % (ud.basecmd), d, workdir=destdir)
+            runfetchcmd("chmod u+w -R %s/.git/annex" % (destdir), d, quiet=True, workdir=destdir)
 
diff --git a/lib/bb/fetch2/gitsm.py b/lib/bb/fetch2/gitsm.py
index 5869e1b99..d9ebe8d18 100644
--- a/lib/bb/fetch2/gitsm.py
+++ b/lib/bb/fetch2/gitsm.py
@@ -205,14 +205,16 @@ class GitSM(Git):
         self.call_process_submodules(ud, d, self.need_update(ud, d), download_submodule)
 
     def unpack(self, ud, destdir, d):
+        subdestdir = self.destdir(ud, destdir, d)
+
         def unpack_submodules(ud, url, module, modpath, workdir, d):
             url += ";bareclone=1;nobranch=1"
 
             # Figure out where we clone over the bare submodules...
             if ud.bareclone:
-                repo_conf = ud.destdir
+                repo_conf = ''
             else:
-                repo_conf = os.path.join(ud.destdir, '.git')
+                repo_conf = '.git'
 
             try:
                 newfetch = Fetch([url], d, cache=False)
@@ -220,7 +222,7 @@ class GitSM(Git):
                 # checkout dir
                 new_ud = newfetch.ud[url]
                 new_ud.modpath = modpath
-                newfetch.unpack(root=os.path.dirname(os.path.join(repo_conf, 'modules', module)))
+                newfetch.unpack(root=os.path.dirname(os.path.join(subdestdir, repo_conf, 'modules', module)))
             except Exception as e:
                 logger.error('gitsm: submodule unpack failed: %s %s' % (type(e).__name__, str(e)))
                 raise
@@ -228,28 +230,28 @@ class GitSM(Git):
             local_path = newfetch.localpath(url)
 
             # Correct the submodule references to the local download version...
-            runfetchcmd("%(basecmd)s config submodule.%(module)s.url %(url)s" % {'basecmd': ud.basecmd, 'module': module, 'url' : local_path}, d, workdir=ud.destdir)
+            runfetchcmd("%(basecmd)s config submodule.%(module)s.url %(url)s" % {'basecmd': ud.basecmd, 'module': module, 'url' : local_path}, d, workdir=subdestdir)
 
             if ud.shallow:
-                runfetchcmd("%(basecmd)s config submodule.%(module)s.shallow true" % {'basecmd': ud.basecmd, 'module': module}, d, workdir=ud.destdir)
+                runfetchcmd("%(basecmd)s config submodule.%(module)s.shallow true" % {'basecmd': ud.basecmd, 'module': module}, d, workdir=subdestdir)
 
             # Ensure the submodule repository is NOT set to bare, since we're checking it out...
             try:
-                runfetchcmd("%s config core.bare false" % (ud.basecmd), d, quiet=True, workdir=os.path.join(repo_conf, 'modules', module))
+                runfetchcmd("%s config core.bare false" % (ud.basecmd), d, quiet=True, workdir=os.path.join(subdestdir, repo_conf, 'modules', module))
             except:
-                logger.error("Unable to set git config core.bare to false for %s" % os.path.join(repo_conf, 'modules', module))
+                logger.error("Unable to set git config core.bare to false for %s" % os.path.join(subdestdir, repo_conf, 'modules', module))
                 raise
 
         Git.unpack(self, ud, destdir, d)
 
-        ret = self.process_submodules(ud, ud.destdir, unpack_submodules, d)
+        ret = self.process_submodules(ud, subdestdir, unpack_submodules, d)
 
         if not ud.bareclone and ret:
             cmdprefix = ""
             # Avoid LFS smudging (replacing the LFS pointers with the actual content) when LFS shouldn't be used but git-lfs is installed.
             if not self._need_lfs(ud):
                 cmdprefix = "GIT_LFS_SKIP_SMUDGE=1 "
-            runfetchcmd("%s%s submodule update --recursive --no-fetch" % (cmdprefix, ud.basecmd), d, quiet=True, workdir=ud.destdir)
+            runfetchcmd("%s%s submodule update --recursive --no-fetch" % (cmdprefix, ud.basecmd), d, quiet=True, workdir=subdestdir)
     def clean(self, ud, d):
         def clean_submodule(ud, url, module, modpath, workdir, d):
             url += ";bareclone=1;nobranch=1"
