diff --git a/mercurial/revset.py b/mercurial/revset.py
index bd98d073a34fcf9651a77a9265878db1f7c88044_bWVyY3VyaWFsL3JldnNldC5weQ==..8b99e9a8db05d77937a9905cc77e946171159acc_bWVyY3VyaWFsL3JldnNldC5weQ== 100644
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -2098,7 +2098,6 @@
     "parent": parentspec,
     "parentpost": p1,
     "only": only,
-    "onlypost": only,
 }
 
 def optimize(x, small):
@@ -2115,6 +2114,8 @@
     elif op == 'only':
         return optimize(('func', ('symbol', 'only'),
                          ('list', x[1], x[2])), small)
+    elif op == 'onlypost':
+        return optimize(('func', ('symbol', 'only'), x[1]), small)
     elif op == 'dagrangepre':
         return optimize(('func', ('symbol', 'ancestors'), x[1]), small)
     elif op == 'dagrangepost':
diff --git a/tests/test-revset.t b/tests/test-revset.t
index bd98d073a34fcf9651a77a9265878db1f7c88044_dGVzdHMvdGVzdC1yZXZzZXQudA==..8b99e9a8db05d77937a9905cc77e946171159acc_dGVzdHMvdGVzdC1yZXZzZXQudA== 100644
--- a/tests/test-revset.t
+++ b/tests/test-revset.t
@@ -533,6 +533,29 @@
   8
   9
 
+Test opreand of '%' is optimized recursively (issue4670)
+
+  $ try --optimize '8:9-8%'
+  (onlypost
+    (minus
+      (range
+        ('symbol', '8')
+        ('symbol', '9'))
+      ('symbol', '8')))
+  * optimized:
+  (func
+    ('symbol', 'only')
+    (and
+      (range
+        ('symbol', '8')
+        ('symbol', '9'))
+      (not
+        ('symbol', '8'))))
+  * set:
+  <baseset+ [8, 9]>
+  8
+  9
+
 Test the order of operations
 
   $ log '7 + 9%5 + 2'