diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
--- a/mercurial/help/config.txt
+++ b/mercurial/help/config.txt
@@ -1345,14 +1345,26 @@ Controls generic server settings.
     Whether to allow clients to push and pull using the legacy bundle1
     exchange format. (default: True)
 
+``bundle1gd``
+    Like ``bundle1` but only used if the repository is using the
+    *generaldelta* storage format. (default: True)
+
 ``bundle1.push``
     Whether to allow clients to push using the legacy bundle1 exchange
     format. (default: True)
 
+``bundle1gd.push``
+    Like ``bundle1.push` but only used if the repository is using the
+    *generaldelta* storage format. (default: True)
+
 ``bundle1.pull``
     Whether to allow clients to pull using the legacy bundle1 exchange
     format. (default: True)
 
+``bundle1gd.pull``
+    Like ``bundle1.pull` but only used if the repository is using the
+    *generaldelta* storage format. (default: True)
+
     Large repositories using the *generaldelta* storage format should
     consider setting this option because converting *generaldelta*
     repositories to the exchange format required by the bundle1 data
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -491,12 +491,33 @@ def options(cmd, keys, others):
                          % (cmd, ",".join(others)))
     return opts
 
-def bundle1allowed(ui, action):
-    """Whether a bundle1 operation is allowed from the server."""
+def bundle1allowed(repo, action):
+    """Whether a bundle1 operation is allowed from the server.
+
+    Priority is:
+
+    1. server.bundle1gd.<action> (if generaldelta active)
+    2. server.bundle1.<action>
+    3. server.bundle1gd (if generaldelta active)
+    4. server.bundle1
+    """
+    ui = repo.ui
+    gd = 'generaldelta' in repo.requirements
+
+    if gd:
+        v = ui.configbool('server', 'bundle1gd.%s' % action, None)
+        if v is not None:
+            return v
+
     v = ui.configbool('server', 'bundle1.%s' % action, None)
     if v is not None:
         return v
 
+    if gd:
+        v = ui.configbool('server', 'bundle1gd', None)
+        if v is not None:
+            return v
+
     return ui.configbool('server', 'bundle1', True)
 
 # list of commands
@@ -665,7 +686,7 @@ def getbundle(repo, proto, others):
             raise KeyError('unknown getbundle option type %s'
                            % keytype)
 
-    if not bundle1allowed(repo.ui, 'pull'):
+    if not bundle1allowed(repo, 'pull'):
         if not exchange.bundle2requested(opts.get('bundlecaps')):
             return ooberror(bundle2required)
 
@@ -781,7 +802,7 @@ def unbundle(repo, proto, heads):
             fp.seek(0)
             gen = exchange.readbundle(repo.ui, fp, None)
             if (isinstance(gen, changegroupmod.cg1unpacker)
-                and not bundle1allowed(repo.ui, 'push')):
+                and not bundle1allowed(repo, 'push')):
                 return ooberror(bundle2required)
 
             r = exchange.unbundle(repo, gen, their_heads, 'serve',
diff --git a/tests/test-bundle2-exchange.t b/tests/test-bundle2-exchange.t
--- a/tests/test-bundle2-exchange.t
+++ b/tests/test-bundle2-exchange.t
@@ -977,6 +977,51 @@ Servers can disable bundle1 for clone/pu
   (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
   [255]
   $ killdaemons.py
+  $ cd ..
+
+bundle1 can still pull non-generaldelta repos when generaldelta bundle1 disabled
+
+  $ hg --config format.usegeneraldelta=false init notgdserver
+  $ cd notgdserver
+  $ cat > .hg/hgrc << EOF
+  > [server]
+  > bundle1gd.pull = false
+  > EOF
+
+  $ touch foo
+  $ hg -q commit -A -m initial
+  $ hg serve -p $HGPORT -d --pid-file=hg.pid
+  $ cat hg.pid >> $DAEMON_PIDS
+
+  $ hg --config experimental.bundle2-exp=false clone http://localhost:$HGPORT/ not-bundle2-1
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ killdaemons.py
+  $ cd ../bundle2onlyserver
+
+bundle1 pull can be disabled for generaldelta repos only
+
+  $ cat > .hg/hgrc << EOF
+  > [server]
+  > bundle1gd.pull = false
+  > EOF
+
+  $ hg serve -p $HGPORT -d --pid-file=hg.pid
+  $ cat hg.pid >> $DAEMON_PIDS
+  $ hg --config experimental.bundle2-exp=false clone http://localhost:$HGPORT/ not-bundle2
+  requesting all changes
+  abort: remote error:
+  incompatible Mercurial client; bundle2 required
+  (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
+  [255]
+
+  $ killdaemons.py
 
 Verify the global server.bundle1 option works
 
@@ -994,6 +1039,42 @@ Verify the global server.bundle1 option 
   [255]
   $ killdaemons.py
 
+  $ cat > .hg/hgrc << EOF
+  > [server]
+  > bundle1gd = false
+  > EOF
+  $ hg serve -p $HGPORT -d --pid-file=hg.pid
+  $ cat hg.pid >> $DAEMON_PIDS
+
+  $ hg --config experimental.bundle2-exp=false clone http://localhost:$HGPORT/ not-bundle2
+  requesting all changes
+  abort: remote error:
+  incompatible Mercurial client; bundle2 required
+  (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
+  [255]
+
+  $ killdaemons.py
+
+  $ cd ../notgdserver
+  $ cat > .hg/hgrc << EOF
+  > [server]
+  > bundle1gd = false
+  > EOF
+  $ hg serve -p $HGPORT -d --pid-file=hg.pid
+  $ cat hg.pid >> $DAEMON_PIDS
+
+  $ hg --config experimental.bundle2-exp=false clone http://localhost:$HGPORT/ not-bundle2-2
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ killdaemons.py
+  $ cd ../bundle2onlyserver
+
 Verify bundle1 pushes can be disabled
 
   $ cat > .hg/hgrc << EOF