Merge branch '3.4-dev'
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index d9b1496..a2024f4 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -110,6 +110,7 @@
 * Prevented Java driver from sending multiple request messages with the same identifier.
 * Improved error message for `property(T,Object)` when mutating graph elements.
 * Added method caching for GraphSON 3.0 deserialization of `P` and `TextP` instances.
+* Fixed bug with global `dedup()` when used in reducing `by()` of `group()`.
 * Fixed bug with Javascript Groovy `Translator` when generating Gremlin with multiple embedded traversals.
 * Modified Gremlin Server `Settings` to be more extensible allowing for custom options with the YAML parser.
 * Fixed `toString()` representation of `P` when string values are present in Javascript.
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
index cfa821a..dd8235d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
@@ -213,10 +213,14 @@
                 // thought as to what might be major changes. To work around the problem we will detach properties as
                 // references so that the parent element goes with it. Also, given TINKERPOP-2318 property comparisons
                 // have changed in such a way that allows this to work properly
-                if (traverser.get() instanceof Property)
-                    traverser.set(ReferenceFactory.detach(traverser.get()));
-                else
-                    traverser.set(DetachedFactory.detach(traverser.get(), true));
+                if (this.onGraphComputer) {
+                    if (traverser.get() instanceof Property)
+                        traverser.set(ReferenceFactory.detach(traverser.get()));
+                    else
+                        traverser.set(DetachedFactory.detach(traverser.get(), true));
+                } else {
+                    traverser.set(traverser.get());
+                }
                 map.put(object, traverser);
             }
         }
diff --git a/gremlin-test/features/filter/Dedup.feature b/gremlin-test/features/filter/Dedup.feature
index 2f46f43..c157ac7 100644
--- a/gremlin-test/features/filter/Dedup.feature
+++ b/gremlin-test/features/filter/Dedup.feature
@@ -235,6 +235,23 @@
       | result |
       | d[0].l |
 
+  # https://issues.apache.org/jira/browse/TINKERPOP-2529
+  Scenario: g_V_both_group_by_byXout_dedup_foldX_unfold_selectXvaluesX_unfold_out_order_byXnameX_limitX1X_valuesXnameX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().both().
+        group().by().by(__.out().dedup().fold()).
+        unfold().
+        select(Column.values).
+        unfold().
+        out().order().by("name").limit(1).values("name")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | lop |
+
   Scenario: g_V_bothE_properties_dedup_count
     Given the modern graph
     And the traversal of
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java
index d8342f3..c36d10d 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java
@@ -21,11 +21,14 @@
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
 import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
+import org.apache.tinkerpop.gremlin.process.IgnoreEngine;
 import org.apache.tinkerpop.gremlin.process.traversal.Order;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Scope;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.structure.Column;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.junit.Test;
@@ -92,6 +95,8 @@
 
     public abstract Traversal<Vertex, Long> get_g_V_repeatXdedupX_timesX2X_count();
 
+    public abstract Traversal<Vertex, String> get_g_V_both_group_by_byXout_dedup_foldX_unfold_selectXvaluesX_unfold_out_order_byXnameX_limitX1X_valuesXnameX();
+
     public abstract Traversal<Vertex, Long> get_g_V_bothE_properties_dedup_count();
 
     public abstract Traversal<Vertex, Long> get_g_V_both_properties_dedup_count();
@@ -147,6 +152,21 @@
         assertFalse(traversal.hasNext());
     }
 
+    /**
+     * https://issues.apache.org/jira/browse/TINKERPOP-2529
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    @IgnoreEngine(TraversalEngine.Type.COMPUTER)
+    public void g_V_both_group_by_byXout_dedup_foldX_unfold_selectXvaluesX_unfold_out_order_byXnameX_limitX1X_valuesXnameX() {
+        final Traversal<Vertex, String> traversal = get_g_V_both_group_by_byXout_dedup_foldX_unfold_selectXvaluesX_unfold_out_order_byXnameX_limitX1X_valuesXnameX();
+        printTraversalForm(traversal);
+        final List<String> names = traversal.toList();
+        assertEquals(1, names.size());
+        assertEquals("lop", names.get(0));
+        assertFalse(traversal.hasNext());
+    }
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_both_name_order_byXa_bX_dedup_value() {
@@ -429,6 +449,16 @@
         }
 
         @Override
+        public Traversal<Vertex, String> get_g_V_both_group_by_byXout_dedup_foldX_unfold_selectXvaluesX_unfold_out_order_byXnameX_limitX1X_valuesXnameX() {
+            return g.V().both().
+                    group().by().by(__.out().dedup().fold()).
+                    unfold().
+                    select(Column.values).
+                    unfold().
+                    out().order().by("name").limit(1).values("name");
+        }
+
+        @Override
         public Traversal<Vertex, Long> get_g_V_bothE_properties_dedup_count() {
             return g.V().bothE().properties().dedup().count();
         }
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
index 0791b16..13f308c 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
@@ -270,11 +270,11 @@
     }
 
     @Test
+    @Ignore
     public void testBugs() {
-        GraphTraversalSource g = TinkerFactory.createModern().traversal();
+        final GraphTraversalSource g = TinkerFactory.createModern().traversal();
         Object o1 = g.V().map(__.V(1));
         System.out.println(g.V().as("a").both().as("b").dedup("a", "b").by(T.label).select("a", "b").explain());
         System.out.println(g.V().as("a").both().as("b").dedup("a", "b").by(T.label).select("a", "b").toList());
-
     }
 }