diff --git oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/PathUtils.java oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/PathUtils.java
index 7ab6b57..9075910 100644
--- oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/PathUtils.java
+++ oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/PathUtils.java
@@ -18,11 +18,14 @@ package org.apache.jackrabbit.oak.commons;
 
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import javax.annotation.Nonnull;
 
+import static com.google.common.collect.Sets.newHashSet;
+
 /**
  * Utility methods to parse a path.
  * <p>
@@ -436,4 +439,42 @@ public final class PathUtils {
         return true;
     }
 
+    /**
+     * Removes paths from {@code includePaths} that are completely excluded
+     * and only retains paths in {@code excludedPaths} that are included. Also
+     * reduces superfluous includes like /a, /a/b to /a.
+     *
+     * <ul>
+     *     <li>[{/a, /a/b}, {}] => [{/a}, {}]</li>
+     *     <li>[{/a}, {/c}] => [{/a}, {}]</li>
+     *     <li>[{/a, /a/b}, {/a/b}] => [{/a}, {/a/b}]</li>
+     * </ul>
+     *
+     * @param includePaths set of paths to be included
+     * @param excludedPaths set of paths to be excluded
+     */
+    public static void optimiseIncludeAndExcludes(Set<String> includePaths, Set<String> excludedPaths) {
+        Set<String> retain = newHashSet();
+        Set<String> includesRemoved = newHashSet();
+        for (String include : includePaths) {
+            for (String exclude : excludedPaths) {
+                if (exclude.equals(include) || isAncestor(exclude, include)) {
+                    includesRemoved.add(include);
+                } else if (isAncestor(include, exclude)) {
+                    retain.add(exclude);
+                }
+            }
+
+            //Remove redundant includes /a, /a/b -> /a
+            for (String include2 : includePaths) {
+                if (isAncestor(include, include2)) {
+                    includesRemoved.add(include2);
+                }
+            }
+        }
+        includePaths.removeAll(includesRemoved);
+        excludedPaths.retainAll(retain);
+    }
+
+
 }
diff --git oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/PathUtilsTest.java oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/PathUtilsTest.java
index 940bda1..dfdfbf2 100644
--- oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/PathUtilsTest.java
+++ oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/PathUtilsTest.java
@@ -16,11 +16,17 @@
  */
 package org.apache.jackrabbit.oak.commons;
 
+import java.util.Set;
+
+import com.google.common.collect.Sets;
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 import org.junit.Assert;
 import org.junit.Test;
 
+import static com.google.common.collect.Sets.newHashSet;
+import static org.junit.Assert.assertEquals;
+
 /**
  * Test the PathUtils class.
  */
@@ -476,4 +482,30 @@ public class PathUtilsTest extends TestCase {
         assertEquals(3, k);
     }
 
+    public void testOptimizeForIncludes() throws Exception{
+        Set<String> includes = newHashSet("/a", "/a/b");
+        Set<String> excludes = newHashSet("/a/b");
+        PathUtils.optimiseIncludeAndExcludes(includes, excludes);
+        assertEquals("Excludes supercedes include", newHashSet("/a"), includes);
+        assertEquals(newHashSet("/a/b"), excludes);
+
+        includes = newHashSet("/a", "/a/b/c");
+        excludes = newHashSet("/a/b");
+        PathUtils.optimiseIncludeAndExcludes(includes, excludes);
+        assertEquals("Excludes supercedes include", newHashSet("/a"), includes);
+        assertEquals(newHashSet("/a/b"), excludes);
+
+        includes = newHashSet("/a", "/a/b/c");
+        excludes = newHashSet();
+        PathUtils.optimiseIncludeAndExcludes(includes, excludes);
+        assertEquals(newHashSet("/a"), includes);
+    }
+
+    public void testOptimizeForExcludes() throws Exception{
+        Set<String> includes = newHashSet("/a", "/b");
+        Set<String> excludes = newHashSet("/c");
+        PathUtils.optimiseIncludeAndExcludes(includes, excludes);
+        assertEquals(newHashSet("/a", "/b"), includes);
+        assertEquals(newHashSet(), excludes);
+    }
 }
