diff --git a/hgext/narrow/narrowchangegroup.py b/hgext/narrow/narrowchangegroup.py
--- a/hgext/narrow/narrowchangegroup.py
+++ b/hgext/narrow/narrowchangegroup.py
@@ -13,6 +13,7 @@ from mercurial import (
     error,
     extensions,
     manifest,
+    match as matchmod,
     mdiff,
     node,
     revlog,
@@ -21,12 +22,19 @@ from mercurial import (
 
 def setup():
 
+    def _cgmatcher(cgpacker):
+        localmatcher = getattr(cgpacker._repo, 'narrowmatch', lambda: None)()
+        remotematcher = getattr(cgpacker, '_narrow_matcher', lambda: None)()
+        if localmatcher and remotematcher:
+            return matchmod.intersectmatchers(localmatcher, remotematcher)
+        else:
+            return localmatcher or remotematcher
+
     def prune(orig, self, revlog, missing, commonrevs):
         if isinstance(revlog, manifest.manifestrevlog):
-            matcher = getattr(self._repo, 'narrowmatch',
-                              getattr(self, '_narrow_matcher', None))
-            if (matcher is not None and
-                not matcher().visitdir(revlog._dir[:-1] or '.')):
+            matcher = _cgmatcher(self)
+            if (matcher and
+                not matcher.visitdir(revlog._dir[:-1] or '.')):
                 return []
         return orig(self, revlog, missing, commonrevs)
 
@@ -34,11 +42,9 @@ def setup():
 
     def generatefiles(orig, self, changedfiles, linknodes, commonrevs,
                       source):
-        matcher = getattr(self._repo, 'narrowmatch',
-                          getattr(self, '_narrow_matcher', None))
-        if matcher is not None:
-            narrowmatch = matcher()
-            changedfiles = [f for f in changedfiles if narrowmatch(f)]
+        matcher = _cgmatcher(self)
+        if matcher:
+            changedfiles = filter(matcher, changedfiles)
         if getattr(self, 'is_shallow', False):
             # See comment in generate() for why this sadness is a thing.
             mfdicts = self._mfdicts
diff --git a/tests/test-narrow-exchange.t b/tests/test-narrow-exchange.t
--- a/tests/test-narrow-exchange.t
+++ b/tests/test-narrow-exchange.t
@@ -137,13 +137,12 @@ narrow spec
   $ hg pull ssh://user@dummy/narrow2
   pulling from ssh://user@dummy/narrow2
   searching for changes
-  remote: abort: unable to resolve parent while packing 'data/inside2/f.i' 3 for changeset 5 (?)
   adding changesets
-  remote: abort: unexpected error: unable to resolve parent while packing 'data/inside2/f.i' 3 for changeset 5
-  transaction abort!
-  rollback completed
-  abort: pull failed on remote
-  [255]
+  adding manifests
+  adding file changes
+  added 1 changesets with 0 changes to 0 files
+  new changesets d78a96df731d
+  (run 'hg update' to get a working copy)
 
 Check that the resulting history is valid in the full repo
 
@@ -204,7 +203,7 @@ necessary content to be able to push to 
   $ hg push ssh://user@dummy/narrow2
   pushing to ssh://user@dummy/narrow2
   searching for changes
-  remote has heads on branch 'default' that are not known locally: d78a96df731d
-  abort: push creates new remote head 5970befb64ba!
-  (pull and merge or see 'hg help push' for details about pushing new heads)
-  [255]
+  remote: adding changesets
+  remote: adding manifests
+  remote: adding file changes
+  remote: added 1 changesets with 0 changes to 0 files