diff -urN hg-git-0.5.0-orig/hggit/git_handler.py hg-git-0.5.0/hggit/git_handler.py
--- hg-git-0.5.0-orig/hggit/git_handler.py	2013-12-14 10:12:43 +0900
+++ hg-git-0.5.0/hggit/git_handler.py	2015-12-19 00:18:13 +0900
@@ -8,6 +8,7 @@
 from dulwich import client
 from dulwich import config as dul_config
 
+from mercurial import hg
 try:
     from mercurial import bookmarks
     bookmarks.update
@@ -207,7 +208,7 @@
 
         oldrefs = self.git.get_refs()
         if refs:
-            self.import_git_objects(remote_name, refs)
+            self.import_git_objects(remote, refs)
             self.import_tags(refs)
             self.update_hg_bookmarks(refs)
             if remote_name:
@@ -632,17 +633,18 @@
 
         return convert_list, [commit for commit in commits if not commit in self._map_git]
 
-    def import_git_objects(self, remote_name=None, refs=None):
+    def import_git_objects(self, remote, refs=None):
         convert_list, commits = self.getnewgitcommits(refs)
         # import each of the commits, oldest first
         total = len(commits)
         if total:
             self.ui.status(_("importing git objects into hg\n"))
 
+        imported_submodules = {}
         for i, csha in enumerate(commits):
             util.progress(self.ui, 'importing', i, total=total, unit='commits')
             commit = convert_list[csha]
-            self.import_git_commit(commit)
+            self.import_git_commit(commit, remote, imported_submodules)
         util.progress(self.ui, 'importing', None, total=total, unit='commits')
 
         # Remove any dangling tag references.
@@ -669,7 +671,7 @@
                     # Mercurial 2.0 and later.
                     del self.repo.tagscache._tagtypes[name]
 
-    def import_git_commit(self, commit):
+    def import_git_commit(self, commit, remote, imported_submodules):
         self.ui.debug(_("importing: %s\n") % commit.id)
 
         (strip_message, hg_renames,
@@ -682,24 +684,34 @@
         gitlinks = self.collect_gitlinks(commit.tree)
         git_commit_tree = self.git[commit.tree]
 
-        # Analyze hgsubstate and build an updated version
-        # using SHAs from gitlinks
-        hgsubstate = None
-        if gitlinks:
-            hgsubstate = util.parse_hgsubstate(self.git_file_readlines(git_commit_tree, '.hgsubstate'))
-            for path, sha in gitlinks:
-                hgsubstate[path] = sha
-            # in case .hgsubstate wasn't among changed files
-            # force its inclusion
-            files['.hgsubstate'] = (False, 0100644, None)
-
         # Analyze .hgsub and merge with .gitmodules
         hgsub = None
         gitmodules = self.parse_gitmodules(git_commit_tree)
         if gitmodules or gitlinks:
             hgsub = util.parse_hgsub(self.git_file_readlines(git_commit_tree, '.hgsub'))
             for (sm_path, sm_url, sm_name) in gitmodules:
-                hgsub[sm_path] = '[git]' + sm_url
+                if sm_url.startswith('git://') or sm_url.startswith('http://') or sm_url.startswith('https://'):
+                    git_url = 'git://' + sm_url.split('//', 1)[1]
+                    if git_url == remote:
+                        self.repo.ui.warn('Skipping import of self-referential submodule %s in commit %s.\n' % (sm_path, commit.id))
+                        continue
+                    else:
+                        hgsub[sm_path] = '[hg]' + git_url
+                        if gitlinks and sm_path in gitlinks:
+                            git_sha = gitlinks[sm_path]
+                            gitlinks[sm_path] = self._map_subrepo_sha(sm_path, git_url, git_sha)
+                            if gitlinks[sm_path]:
+                                hgsub[sm_path] = sm_path
+                            else:
+                                if sm_path not in imported_submodules:
+                                    self.repo.ui.warn('Skipping import of submodule %s (at nonexistent commit %s) in commit %s.\n' % (sm_path, git_sha, commit.id))
+                                elif imported_submodules[sm_path] != git_sha:
+                                    self.repo.ui.warn('Skipping update of submodule %s (to nonexistent commit %s) in commit %s.\n' % (sm_path, git_sha, commit.id))
+                            imported_submodules[sm_path] = git_sha
+                        else:
+                            imported_submodules[sm_path] = None
+                else:
+                    hgsub[sm_path] = '[git]' + sm_url
             files['.hgsub'] = (False, 0100644, None)
         elif commit.parents and '.gitmodules' in self.git[self.git[commit.parents[0]].tree]:
             # no .gitmodules in this commit, however present in the parent
@@ -707,6 +719,18 @@
             # due to the same import_git_commit process
             files['.hgsub'] = (True, 0100644, None)
 
+        # Analyze hgsubstate and build an updated version
+        # using SHAs from gitlinks
+        hgsubstate = None
+        if gitlinks:
+            hgsubstate = util.parse_hgsubstate(self.git_file_readlines(git_commit_tree, '.hgsubstate'))
+            for path, sha in gitlinks.iteritems():
+                if sha:
+                    hgsubstate[path] = sha
+            # in case .hgsubstate wasn't among changed files
+            # force its inclusion
+            files['.hgsubstate'] = (False, 0100644, None)
+
         date = (commit.author_time, -commit.author_timezone)
         text = strip_message
 
@@ -1271,13 +1295,13 @@
           :return: list of tuples (commit sha, full entry path)
         """
         queue = [(tree_id, '')]
-        gitlinks = []
+        gitlinks = {}
         while queue:
             e, path = queue.pop(0)
             o = self.git.object_store[e]
             for (name, mode, sha) in o.iteritems():
                 if mode == S_IFGITLINK:
-                    gitlinks.append((posixpath.join(path, name), sha))
+                    gitlinks[posixpath.join(path, name)] = sha
                 elif stat.S_ISDIR(mode):
                     queue.append((sha, posixpath.join(path, name)))
         return gitlinks
@@ -1379,3 +1403,18 @@
 
         # if its not git or git+ssh, try a local url..
         return client.SubprocessGitClient(thin_packs=False), uri
+
+    def _map_subrepo_sha(self, path, remote, gitsha):
+        """Return the Mercurial node ID corresponding to the given Git node.
+
+        Assumes path is a repository cloned (or to be cloned) with hg-git.
+        If path does not exist, it is cloned from the given remote repo.
+        """
+        try:
+            subrepo = hg.repository(self.ui, self.repo.wjoin(path))
+        except RepoError:
+            self.ui.status(_('cloning submodule %s from %s\n' % (path, remote)))
+            commands.clone(self.ui, remote, self.repo.wjoin(path))
+            subrepo = hg.repository(self.ui, self.repo.wjoin(path))
+        handler = GitHandler(subrepo, self.ui)
+        return handler.map_hg_get(gitsha)
