diff --git a/mercurial/fileset.py b/mercurial/fileset.py
index 951d95b13487d06636cb21a58f8df0699897691b_bWVyY3VyaWFsL2ZpbGVzZXQucHk=..4140d49d2efb0f73d24fc5bd3614a1b25f1d3270_bWVyY3VyaWFsL2ZpbGVzZXQucHk= 100644
--- a/mercurial/fileset.py
+++ b/mercurial/fileset.py
@@ -15,6 +15,7 @@
     merge,
     parser,
     registrar,
+    scmutil,
     util,
 )
 
@@ -438,6 +439,30 @@
             s.append(f)
     return s
 
+@predicate('revs(revs, pattern)')
+def revs(mctx, x):
+    """``revs(set, revspec)``
+
+    Evaluate set in the specified revisions. If the revset match multiple revs,
+    this will return file matching pattern in any of the revision.
+    """
+    # i18n: "revs" is a keyword
+    r, x = getargs(x, 2, 2, _("revs takes two arguments"))
+    # i18n: "revs" is a keyword
+    revspec = getstring(r, _("first argument to revs must be a revision"))
+    repo = mctx.ctx.repo()
+    revs = scmutil.revrange(repo, [revspec])
+
+    found = set()
+    result = []
+    for r in revs:
+        ctx = repo[r]
+        for f in getset(mctx.switch(ctx, _buildstatus(ctx, x)), x):
+            if f not in found:
+                found.add(f)
+                result.append(f)
+    return result
+
 @predicate('subrepo([pattern])')
 def subrepo(mctx, x):
     """Subrepositories whose paths match the given pattern.
@@ -512,6 +537,7 @@
 
 # filesets using matchctx.switch()
 _switchcallers = [
+    'revs',
 ]
 
 def _intree(funcs, tree):
diff --git a/mercurial/help/filesets.txt b/mercurial/help/filesets.txt
index 951d95b13487d06636cb21a58f8df0699897691b_bWVyY3VyaWFsL2hlbHAvZmlsZXNldHMudHh0..4140d49d2efb0f73d24fc5bd3614a1b25f1d3270_bWVyY3VyaWFsL2hlbHAvZmlsZXNldHMudHh0 100644
--- a/mercurial/help/filesets.txt
+++ b/mercurial/help/filesets.txt
@@ -69,6 +69,10 @@
 
     hg revert "set:copied() and binary() and size('>1M')"
 
+- Revert files that were added to the working directory::
+
+    hg revert "set:wdir(added())"
+
 - Remove files listed in foo.lst that contain the letter a or b::
 
     hg remove "set: 'listfile:foo.lst' and (**a* or **b*)"
diff --git a/tests/test-fileset.t b/tests/test-fileset.t
index 951d95b13487d06636cb21a58f8df0699897691b_dGVzdHMvdGVzdC1maWxlc2V0LnQ=..4140d49d2efb0f73d24fc5bd3614a1b25f1d3270_dGVzdHMvdGVzdC1maWxlc2V0LnQ= 100644
--- a/tests/test-fileset.t
+++ b/tests/test-fileset.t
@@ -88,6 +88,35 @@
   $ fileset 'copied()'
   c1
 
+Test files status in different revisions
+
+  $ hg status -m
+  M b2
+  $ fileset -r0 'revs("wdir()", modified())' --traceback
+  b2
+  $ hg status -a
+  A c1
+  $ fileset -r0 'revs("wdir()", added())'
+  c1
+  $ hg status --change 0 -a
+  A a1
+  A a2
+  A b1
+  A b2
+  $ hg status -mru
+  M b2
+  R a2
+  ? c3
+  $ fileset -r0 'added() and revs("wdir()", modified() or removed() or unknown())'
+  b2
+  a2
+  $ fileset -r0 'added() or revs("wdir()", added())'
+  a1
+  a2
+  b1
+  b2
+  c1
+
 Test files properties
 
   >>> file('bin', 'wb').write('\0a')
@@ -367,3 +396,128 @@
 
   $ fileset 'existingcaller()' 2>&1 | tail -1
   AssertionError: unexpected existing() invocation
+
+Test 'revs(...)'
+================
+
+small reminder of the repository state
+
+  $ hg log -G
+  @  changeset:   4:160936123545
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     subrepo
+  |
+  o    changeset:   3:9d594e11b8c9
+  |\   parent:      2:55b05bdebf36
+  | |  parent:      1:830839835f98
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     merge
+  | |
+  | o  changeset:   2:55b05bdebf36
+  | |  parent:      0:8a9576c51c1f
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     diverging
+  | |
+  o |  changeset:   1:830839835f98
+  |/   user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     manychanges
+  |
+  o  changeset:   0:8a9576c51c1f
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     addfiles
+  
+  $ hg status --change 0
+  A a1
+  A a2
+  A b1
+  A b2
+  $ hg status --change 1
+  M b2
+  A 1k
+  A 2k
+  A b2link
+  A bin
+  A c1
+  A con.xml
+  R a2
+  $ hg status --change 2
+  M b2
+  $ hg status --change 3
+  M b2
+  A 1k
+  A 2k
+  A b2link
+  A bin
+  A c1
+  A con.xml
+  R a2
+  $ hg status --change 4
+  A .hgsub
+  A .hgsubstate
+  $ hg status
+  A dos
+  A mac
+  A mixed
+  R con.xml
+  ! a1
+  ? b2.orig
+  ? c3
+  ? unknown
+
+Test files at -r0 should be filtered by files at wdir
+-----------------------------------------------------
+
+  $ fileset -r0 '* and revs("wdir()", *)'
+  a1
+  b1
+  b2
+
+Test that "revs()" work at all
+------------------------------
+
+  $ fileset "revs('2', modified())"
+  b2
+
+Test that "revs()" work for file missing in the working copy/current context
+----------------------------------------------------------------------------
+
+(a2 not in working copy)
+
+  $ fileset "revs('0', added())"
+  a1
+  a2
+  b1
+  b2
+
+(none of the file exist in "0")
+
+  $ fileset -r 0 "revs('4', added())"
+  .hgsub
+  .hgsubstate
+
+Call with empty revset
+--------------------------
+
+  $ fileset "revs('2-2', modified())"
+
+Call with revset matching multiple revs
+---------------------------------------
+
+  $ fileset "revs('0+4', added())"
+  a1
+  a2
+  b1
+  b2
+  .hgsub
+  .hgsubstate
+
+overlapping set
+
+  $ fileset "revs('1+2', modified())"
+  b2