diff --git a/hggit/__init__.py b/hggit/__init__.py
index 1a9e9e0c93041346c9539d188b5870fa328b50d1_aGdnaXQvX19pbml0X18ucHk=..8c5ed2bf842343671c1a47677d846d4a9f34a1b5_aGdnaXQvX19pbml0X18ucHk= 100644
--- a/hggit/__init__.py
+++ b/hggit/__init__.py
@@ -125,9 +125,10 @@
 import os
 
 # local modules
+from . import commands
 from . import compat
 from . import gitrepo
 from . import git_handler
 from . import hgrepo
 from . import overlay
 from . import revsets
@@ -128,9 +129,8 @@
 from . import compat
 from . import gitrepo
 from . import git_handler
 from . import hgrepo
 from . import overlay
 from . import revsets
-from . import verify
 from . import util
 
@@ -135,6 +135,5 @@
 from . import util
 
-from mercurial.node import bin, hex, nullhex
-from mercurial.i18n import _
+from mercurial.node import bin
 from mercurial import (
     bundlerepo,
@@ -139,6 +138,5 @@
 from mercurial import (
     bundlerepo,
-    commands,
     demandimport,
     dirstate,
     discovery,
@@ -142,7 +140,6 @@
     demandimport,
     dirstate,
     discovery,
-    error,
     exchange,
     extensions,
     hg,
@@ -151,7 +148,6 @@
     pycompat,
     registrar,
     repoview,
-    scmutil,
 )
 
 demandimport.IGNORES |= {
@@ -164,5 +160,5 @@
 minimumhgversion = b'5.2'
 buglink = b'https://foss.heptapod.net/mercurial/hg-git/issues'
 
-cmdtable = {}
+cmdtable = commands.cmdtable
 configtable = {}
@@ -168,5 +164,4 @@
 configtable = {}
-command = registrar.command(cmdtable)
 configitem = registrar.configitem(configtable)
 templatekeyword = registrar.templatekeyword()
 
@@ -287,84 +282,6 @@
                         overlay.wrapmanifestdictdiff)
 
 
-@command(b'gimport')
-def gimport(ui, repo, remote_name=None):
-    '''import commits from Git to Mercurial (ADVANCED)
-
-    This command is equivalent to pulling from a Git source, but
-    without actually accessing the network. Internally, hg-git relies
-    on a local, cached git repository containing changes equivalent to
-    the Mercurial repository. If you modify that Git repository
-    somehow, use this command to import those changes.
-
-    '''
-    repo.githandler.import_commits(remote_name)
-
-
-@command(b'gexport')
-def gexport(ui, repo):
-    '''export commits from Mercurial to Git (ADVANCED)
-
-    This command is equivalent to pushing to a Git source, but without
-    actually access the network. Internally, hg-git relies on a local,
-    cached git repository containing changes equivalent to the
-    Mercurial repository. If you wish to see what the Git commits
-    would be, use this command to export those changes. As an example,
-    it ensures that all changesets have a corresponding Git node.
-
-    '''
-    repo.githandler.export_commits()
-
-
-@command(b'gclear')
-def gclear(ui, repo):
-    '''clear out the Git cached data (ADVANCED)
-
-    Strips all Git-related metadata from the repo, including the mapping
-    between Git and Mercurial changesets. This is an irreversible
-    destructive operation that may prevent further interaction with
-    other clones.
-    '''
-    repo.ui.status(_(b"clearing out the git cache data\n"))
-    repo.githandler.clear()
-
-
-@command(b'debuggitdir')
-def gitdir(ui, repo):
-    '''get the root of the git repository'''
-    repo.ui.write(os.path.normpath(repo.githandler.gitdir), b'\n')
-
-
-@command(b'gverify',
-         [(b'r', b'rev', b'', _(b'revision to verify'), _(b'REV'))],
-         _(b'[-r REV]'))
-def gverify(ui, repo, **opts):
-    '''verify that a Mercurial rev matches the corresponding Git rev
-
-    Given a Mercurial revision that has a corresponding Git revision in the
-    map, this attempts to answer whether that revision has the same contents as
-    the corresponding Git revision.
-
-    '''
-    ctx = scmutil.revsingle(repo, opts.get('rev'), b'.')
-    return verify.verify(ui, repo, ctx)
-
-
-@command(b'git-cleanup')
-def git_cleanup(ui, repo):
-    '''clean up Git commit map after history editing'''
-    new_map = []
-    gh = repo.githandler
-    for line in gh.vfs(gh.map_file):
-        gitsha, hgsha = line.strip().split(b' ', 1)
-        if hgsha in repo:
-            new_map.append(b'%s %s\n' % (gitsha, hgsha))
-    with repo.githandler.store_repo.wlock():
-        f = gh.vfs(gh.map_file, b'wb')
-        f.writelines(new_map)
-    ui.status(_(b'git commit map cleaned\n'))
-
-
 def findcommonoutgoing(orig, repo, other, *args, **kwargs):
     if isinstance(other, gitrepo.gitrepo):
         heads = repo.githandler.get_refs(other.path)[0]
@@ -403,89 +320,6 @@
 extensions.wrapfunction(bundlerepo, b'getremotechanges', getremotechanges)
 
 
-def tag(orig, ui, repo, *names, **opts):
-    '''You can also use --git to create a lightweight Git tag. Please note
-    that this requires an explicit -r/--rev, and does not support any
-    of the other flags.
-
-    Support for Git tags is somewhat minimal. The Git documentation
-    heavily discourages changing tags once pushed, and suggests that
-    users always create a new one instead. (Unlike Mercurial, Git does
-    not track and version its tags within the repository.) As result,
-    there's no support for removing and changing preexisting tags.
-    Similarly, there's no support for annotated tags, i.e. tags with
-    messages, nor for signing tags. For those, either use Git directly
-    or use the integrated web interface for tags and releases offered
-    by most hosting solutions, including GitHub and GitLab.
-
-    '''
-
-    if not opts.get('git'):
-        return orig(ui, repo, *names, **opts)
-
-    opts = pycompat.byteskwargs(opts)
-
-    # check for various unimplemented arguments
-    compat.check_incompatible_arguments(opts, b'git', [
-        # conflict
-        b'local',
-        # we currently don't convert or expose this metadata, so
-        # disallow setting it on creation
-        b'edit',
-        b'message',
-        b'date',
-        b'user',
-    ])
-    compat.check_at_most_one_arg(opts, b'rev', b'remove')
-
-    if opts[b'remove']:
-        opts[b'rev'] = b'null'
-
-    if not opts.get(b'rev'):
-        raise error.Abort(_(b'git tags require an explicit revision'),
-                          hint=b'please specify -r/--rev')
-
-    # the semantics of git tag editing are quite confusing, so we
-    # don't bother; if you _really_ want to, use another tool to do
-    # this, and ensure all contributors prune their tags -- otherwise,
-    # it'll reappear next time someone pushes tags (ah, the wonders of
-    # nonversioned markers!)
-    #
-    # see also https://git-scm.com/docs/git-tag#_discussion
-    if opts[b'force']:
-        raise error.Abort(
-            b'cannot move git tags',
-            hint=b'the git documentation heavily discourages editing tags',
-        )
-
-    names = [t.strip() for t in names]
-
-    if len(names) != len(set(names)):
-        raise error.Abort(_('tag names must be unique'))
-
-    with repo.wlock(), repo.lock():
-        target = hex(repo.lookup(opts[b'rev']))
-
-        # see above
-        if target == nullhex:
-            raise error.Abort(
-                b'cannot remove git tags',
-                hint=b'the git documentation heavily discourages editing tags',
-            )
-
-        repo.githandler.add_tag(target, *names)
-
-
-commands.table[b'tag'][1].append((b'', b'git', False,
-                                  b'make it a git tag'))
-extensions.wrapcommand(
-    commands.table,
-    b'tag',
-    tag,
-    docstring='\n\n    ' + tag.__doc__.strip(),
-)
-
-
 def pinnedrevs(orig, repo):
     pinned = orig(repo)
 
diff --git a/hggit/__init__.py b/hggit/commands.py
similarity index 47%
copy from hggit/__init__.py
copy to hggit/commands.py
index 1a9e9e0c93041346c9539d188b5870fa328b50d1_aGdnaXQvX19pbml0X18ucHk=..8c5ed2bf842343671c1a47677d846d4a9f34a1b5_aGdnaXQvY29tbWFuZHMucHk= 100644
--- a/hggit/__init__.py
+++ b/hggit/commands.py
@@ -6,119 +6,6 @@
 # This software may be used and distributed according to the terms
 # of the GNU General Public License, incorporated herein by reference.
 
-r'''push and pull from a Git server
-
-This extension lets you communicate (push and pull) with a Git server.
-This way you can use Git hosting for your project or collaborate with a
-project that is in Git. A bridger of worlds, this plugin be.
-
-Try :hg:`clone git+https://github.com/dulwich/dulwich` or :hg:`clone
-git+ssh://example.com/repo.git`.
-
-Basic Use
----------
-
-You can clone a Git repository from Mercurial by running :hg:`clone
-<url> [dest]`. For example, if you were to run::
-
- $ hg clone git://github.com/schacon/hg-git.git
-
-Hg-Git would clone the repository and convert it to a Mercurial repository for
-you. There are a number of different protocols that can be used for Git
-repositories. Examples of Git repository URLs include::
-
-  git+https://github.com/hg-git/hg-git.git
-  git+http://github.com/hg-git/hg-git.git
-  git+ssh://git@github.com/hg-git/hg-git.git
-  git://github.com/hg-git/hg-git.git
-  file:///path/to/hg-git
-  ../hg-git (local file path)
-
-These also work::
-
-  git+ssh://git@github.com:hg-git/hg-git.git
-  git@github.com:hg-git/hg-git.git
-
-Please note that you need to prepend HTTP, HTTPS, and SSH URLs with
-``git+`` in order differentiate them from Mercurial URLs. For example,
-an HTTPS URL would start with ``git+https://``. Also, note that Git
-doesn't require the specification of the protocol for SSH, but
-Mercurial does. Hg-Git automatically detects whether file paths should
-be treated as Git repositories by their contents.
-
-If you are starting from an existing Mercurial repository, you have to
-set up a Git repository somewhere that you have push access to, add a
-path entry for it in your .hg/hgrc file, and then run :hg:`push
-[name]` from within your repository. For example::
-
- $ cd hg-git # (a Mercurial repository)
- $ # edit .hg/hgrc and add the target Git URL in the paths section
- $ hg push
-
-This will convert all your Mercurial changesets into Git objects and push
-them to the Git server.
-
-Pulling new revisions into a repository is the same as from any other
-Mercurial source. Within the earlier examples, the following commands are
-all equivalent::
-
- $ hg pull
- $ hg pull default
- $ hg pull git://github.com/hg-git/hg-git.git
-
-Git branches are exposed in Mercurial as bookmarks, while Git remote
-branches are exposed as unchangable Mercurial local tags. See
-:hg:`help bookmarks` and :hg:`help tags` for further information.
-
-Finding and displaying Git revisions
-------------------------------------
-
-For displaying the Git revision ID, Hg-Git provides a template keyword:
-
-  :gitnode: String.  The Git changeset identification hash, as a 40 hexadecimal
-    digit string.
-
-For example::
-
-  $ hg log --template='{rev}:{node|short}:{gitnode|short} {desc}\n'
-  $ hg log --template='hg: {node}\ngit: {gitnode}\n{date|isodate} {author}\n{desc}\n\n'
-
-For finding changesets from Git, Hg-Git extends revsets to provide two new
-selectors:
-
-  :fromgit: Select changesets that originate from Git. Takes no arguments.
-  :gitnode: Select changesets that originate in a specific Git revision. Takes
-    a revision argument.
-
-For example::
-
-  $ hg log -r 'fromgit()'
-  $ hg log -r 'gitnode(84f75b909fc3)'
-
-Revsets are accepted by several Mercurial commands for specifying
-revisions. See :hg:`help revsets` for details.
-
-Invalid and dangerous paths
----------------------------
-
-Both Mercurial and Git consider paths as just bytestrings internally,
-and allow almost anything. The difference, however, is in the _almost_
-part. For example, many Git servers will reject a push for security
-reasons if it contains a nested Git repository. Similarly, Mercurial
-cannot checkout commits with a nested repository, and it cannot even
-store paths containing an embedded newline or carrage return
-character.
-
-The default is to issue a warning and skip these paths. You can
-change this by setting ``hggit.invalidpaths`` in :hg:`config`::
-
-  [hggit]
-  invalidpaths = keep
-
-Possible values are ``keep``, ``skip`` or ``abort``.
-
-'''
-
 from __future__ import generator_stop
 
 # global modules
@@ -126,9 +13,4 @@
 
 # local modules
 from . import compat
-from . import gitrepo
-from . import git_handler
-from . import hgrepo
-from . import overlay
-from . import revsets
 from . import verify
@@ -134,3 +16,2 @@
 from . import verify
-from . import util
 
@@ -136,4 +17,4 @@
 
-from mercurial.node import bin, hex, nullhex
+from mercurial.node import hex, nullhex
 from mercurial.i18n import _
 from mercurial import (
@@ -138,4 +19,3 @@
 from mercurial.i18n import _
 from mercurial import (
-    bundlerepo,
     commands,
@@ -141,5 +21,2 @@
     commands,
-    demandimport,
-    dirstate,
-    discovery,
     error,
@@ -145,3 +22,2 @@
     error,
-    exchange,
     extensions,
@@ -147,6 +23,3 @@
     extensions,
-    hg,
-    localrepo,
-    manifest,
     pycompat,
     registrar,
@@ -151,6 +24,5 @@
     pycompat,
     registrar,
-    repoview,
     scmutil,
 )
 
@@ -154,14 +26,4 @@
     scmutil,
 )
 
-demandimport.IGNORES |= {
-    b'collections',
-}
-
-__version__ = b'0.11.0dev'
-
-testedwith = (b'5.2 5.3 5.4 5.5 5.6 5.7 5.8')
-minimumhgversion = b'5.2'
-buglink = b'https://foss.heptapod.net/mercurial/hg-git/issues'
-
 cmdtable = {}
@@ -167,3 +29,2 @@
 cmdtable = {}
-configtable = {}
 command = registrar.command(cmdtable)
@@ -169,123 +30,4 @@
 command = registrar.command(cmdtable)
-configitem = registrar.configitem(configtable)
-templatekeyword = registrar.templatekeyword()
-
-compat.registerconfigs(configitem)
-
-# support for `hg clone git://github.com/defunkt/facebox.git`
-# also hg clone git+ssh://git@github.com/schacon/simplegit.git
-for _scheme in util.gitschemes:
-    hg.schemes[_scheme] = gitrepo
-
-# support for `hg clone localgitrepo`
-_oldlocal = hg.schemes[b'file']
-
-def _isgitdir(path):
-    """True if the given file path is a git repo."""
-    if os.path.exists(os.path.join(path, b'.hg')):
-        return False
-
-    if os.path.exists(os.path.join(path, b'.git')):
-        # is full git repo
-        return True
-
-    if (os.path.exists(os.path.join(path, b'HEAD')) and
-        os.path.exists(os.path.join(path, b'objects')) and
-        os.path.exists(os.path.join(path, b'refs'))):
-        # is bare git repo
-        return True
-
-    return False
-
-
-def _local(path):
-    p = compat.url(path).localpath()
-    if _isgitdir(p):
-        return gitrepo
-    # detect git ssh urls (which mercurial thinks is a file-like path)
-    if util.isgitsshuri(p):
-        return gitrepo
-    return _oldlocal(path)
-
-
-hg.schemes[b'file'] = _local
-
-
-def _httpgitwrapper(orig):
-    # we should probably test the connection but for now, we just keep it
-    # simple and check for a url ending in '.git'
-    def httpgitscheme(uri):
-        if uri.endswith(b'.git'):
-            return gitrepo
-
-        # the http(s) scheme just returns the _peerlookup
-        return orig
-
-    return httpgitscheme
-
-
-hg.schemes[b'https'] = _httpgitwrapper(hg.schemes[b'https'])
-hg.schemes[b'http'] = _httpgitwrapper(hg.schemes[b'http'])
-hgdefaultdest = hg.defaultdest
-
-
-def defaultdest(source):
-    for scheme in util.gitschemes:
-        if source.startswith(b'%s://' % scheme) and source.endswith(b'.git'):
-            return hgdefaultdest(source[:-4])
-
-    if source.endswith(b'.git'):
-        return hgdefaultdest(source[:-4])
-
-    return hgdefaultdest(source)
-
-
-hg.defaultdest = defaultdest
-
-
-def getversion():
-    """return version with dependencies for hg --version -v"""
-    import dulwich
-    dulver = b'.'.join(pycompat.sysbytes(str(i)) for i in dulwich.__version__)
-    return __version__ + (b" (dulwich %s)" % dulver)
-
-
-# defend against tracebacks if we specify -r in 'hg pull'
-def safebranchrevs(orig, lrepo, otherrepo, branches, revs):
-    revs, co = orig(lrepo, otherrepo, branches, revs)
-    if isinstance(otherrepo, gitrepo.gitrepo):
-        # FIXME: Unless it's None, the 'co' result is passed to the lookup()
-        # remote command. Since our implementation of the lookup() remote
-        # command is incorrect, we set it to None to avoid a crash later when
-        # the incorect result of the lookup() remote command would otherwise be
-        # used. This can, in undocumented corner-cases, result in that a
-        # different revision is updated to when passing both -u and -r to
-        # 'hg pull'. An example of such case is in tests/test-addbranchrevs.t
-        # (for the non-hg-git case).
-        co = None
-    return revs, co
-extensions.wrapfunction(hg, b'addbranchrevs', safebranchrevs)
-
-
-def extsetup(ui):
-    revsets.extsetup(ui)
-
-
-def reposetup(ui, repo):
-    if not isinstance(repo, gitrepo.gitrepo):
-        if (getattr(dirstate, 'rootcache', False) and
-            git_handler.has_gitrepo(repo)):
-            # only install our dirstate wrapper if it has a hope of working
-            from . import gitdirstate
-            dirstate.dirstate = gitdirstate.gitdirstate
-
-        klass = hgrepo.generate_repo_subclass(repo.__class__)
-        repo.__class__ = klass
-
-
-extensions.wrapfunction(manifest.manifestdict, b'diff',
-                        overlay.wrapmanifestdictdiff)
-
 
 @command(b'gimport')
 def gimport(ui, repo, remote_name=None):
@@ -365,44 +107,6 @@
     ui.status(_(b'git commit map cleaned\n'))
 
 
-def findcommonoutgoing(orig, repo, other, *args, **kwargs):
-    if isinstance(other, gitrepo.gitrepo):
-        heads = repo.githandler.get_refs(other.path)[0]
-        kw = {}
-        kw.update(kwargs)
-        for val, k in zip(args,
-                          ('onlyheads', 'force', 'commoninc', 'portable')):
-            kw[k] = val
-        force = kw.get('force', False)
-        commoninc = kw.get('commoninc', None)
-        if commoninc is None:
-            commoninc = discovery.findcommonincoming(repo, other, heads=heads,
-                                                     force=force)
-            kw['commoninc'] = commoninc
-        return orig(repo, other, **kw)
-    return orig(repo, other, *args, **kwargs)
-
-
-extensions.wrapfunction(discovery, b'findcommonoutgoing', findcommonoutgoing)
-
-
-def getremotechanges(orig, ui, repo, other, *args, **opts):
-    if isinstance(other, gitrepo.gitrepo):
-        if args:
-            revs = args[0]
-        else:
-            revs = opts.get('onlyheads', opts.get('revs'))
-        r, c, cleanup = repo.githandler.getremotechanges(other, revs)
-        # ugh. This is ugly even by mercurial API compatibility standards
-        if 'onlyheads' not in orig.__code__.co_varnames:
-            cleanup = None
-        return r, c, cleanup
-    return orig(ui, repo, other, *args, **opts)
-
-
-extensions.wrapfunction(bundlerepo, b'getremotechanges', getremotechanges)
-
-
 def tag(orig, ui, repo, *names, **opts):
     '''You can also use --git to create a lightweight Git tag. Please note
     that this requires an explicit -r/--rev, and does not support any
@@ -484,123 +188,3 @@
     tag,
     docstring='\n\n    ' + tag.__doc__.strip(),
 )
-
-
-def pinnedrevs(orig, repo):
-    pinned = orig(repo)
-
-    # Mercurial pins bookmarks, even if obsoleted, so that they always
-    # appear in e.g. log; do the same with git tags and remotes.
-    if repo.local() and hasattr(repo, 'githandler'):
-        rev = repo.changelog.rev
-
-        pinned.update(rev(bin(r)) for r in repo.githandler.tags.values())
-        pinned.update(rev(r) for r in repo.githandler.remote_refs.values())
-
-    return pinned
-
-extensions.wrapfunction(repoview, b'pinnedrevs', pinnedrevs)
-
-
-def peer(orig, uiorrepo, *args, **opts):
-    newpeer = orig(uiorrepo, *args, **opts)
-    if isinstance(newpeer, gitrepo.gitrepo):
-        if isinstance(uiorrepo, localrepo.localrepository):
-            newpeer.localrepo = uiorrepo
-    return newpeer
-
-
-extensions.wrapfunction(hg, b'peer', peer)
-
-
-def isvalidlocalpath(orig, self, path):
-    return orig(self, path) or _isgitdir(path)
-
-
-extensions.wrapfunction(compat.path, b'_isvalidlocalpath', isvalidlocalpath)
-
-
-def isurllocal(orig, path):
-    # recognise git scp-style paths when cloning
-    return orig(path) and not util.isgitsshuri(path._origpath)
-
-
-extensions.wrapfunction(compat.url, b'islocal', isurllocal)
-
-
-def islocal(orig, path):
-    # recognise git scp-style paths when cloning
-    return orig(path) and not util.isgitsshuri(path)
-
-
-extensions.wrapfunction(hg, b'islocal', islocal)
-
-
-def hasscheme(orig, path):
-    # recognise git scp-style paths
-    return orig(path) or util.isgitsshuri(path)
-
-
-extensions.wrapfunction(compat.urlutil, b'hasscheme', hasscheme)
-
-
-@util.transform_notgit
-def exchangepull(orig, repo, remote, heads=None, force=False, bookmarks=(),
-                 **kwargs):
-    if isinstance(remote, gitrepo.gitrepo):
-        pullop = exchange.pulloperation(repo, remote, heads, force,
-                                        bookmarks=bookmarks)
-        pullop.trmanager = exchange.transactionmanager(repo, b'pull',
-                                                       remote.url())
-
-        wlock = repo.wlock()
-        lock = repo.lock()
-        try:
-            pullop.cgresult = repo.githandler.fetch(remote.path, heads)
-            pullop.trmanager.close()
-            return pullop
-        finally:
-            pullop.trmanager.release()
-            lock.release()
-            wlock.release()
-    else:
-        return orig(repo, remote, heads, force, bookmarks=bookmarks, **kwargs)
-
-
-extensions.wrapfunction(exchange, b'pull', exchangepull)
-
-
-# TODO figure out something useful to do with the newbranch param
-@util.transform_notgit
-def exchangepush(orig, repo, remote, force=False, revs=None, newbranch=False,
-                 bookmarks=(), opargs=None, **kwargs):
-    if isinstance(remote, gitrepo.gitrepo):
-        pushop = exchange.pushoperation(repo, remote, force, revs, newbranch,
-                                        bookmarks,
-                                        **pycompat.strkwargs(opargs or {}))
-        pushop.cgresult = repo.githandler.push(remote.path, revs, force)
-        return pushop
-    else:
-        return orig(repo, remote, force, revs, newbranch, bookmarks=bookmarks,
-                    opargs=None, **kwargs)
-
-
-extensions.wrapfunction(exchange, b'push', exchangepush)
-
-
-def _gitnodekw(node, repo):
-    if not hasattr(repo, 'githandler'):
-        return None
-    gitnode = repo.githandler.map_git_get(node.hex())
-    if gitnode is None:
-        gitnode = b''
-    return gitnode
-
-
-@templatekeyword(b'gitnode', requires={b'ctx', b'repo'})
-def gitnodekw(context, mapping):
-    """:gitnode: String. The Git changeset identification hash, as a
-        40 hexadecimal digit string."""
-    node = context.resource(mapping, b'ctx')
-    repo = context.resource(mapping, b'repo')
-    return _gitnodekw(node, repo)