diff --git a/rust/hg-core/src/copy_tracing.rs b/rust/hg-core/src/copy_tracing.rs
index f5c12907957d86dce421983749043e940f2e7cc4_cnVzdC9oZy1jb3JlL3NyYy9jb3B5X3RyYWNpbmcucnM=..aea4b4f82183d3c35530adbdb537e905795b15a7_cnVzdC9oZy1jb3JlL3NyYy9jb3B5X3RyYWNpbmcucnM= 100644
--- a/rust/hg-core/src/copy_tracing.rs
+++ b/rust/hg-core/src/copy_tracing.rs
@@ -323,15 +323,6 @@
 pub type RevInfoMaker<'a, D> =
     Box<dyn for<'r> Fn(Revision, &'r mut DataHolder<D>) -> RevInfo<'r> + 'a>;
 
-/// enum used to carry information about the parent → child currently processed
-#[derive(Copy, Clone, Debug)]
-enum Parent {
-    /// The `p1(x) → x` edge
-    FirstParent,
-    /// The `p2(x) → x` edge
-    SecondParent,
-}
-
 /// A small "tokenizer" responsible of turning full HgPath into lighter
 /// PathToken
 ///
@@ -393,7 +384,6 @@
         // We will chain the copies information accumulated for the parent with
         // the individual copies information the curent revision.  Creating a
         // new TimeStampedPath for each `rev` → `children` vertex.
-        let mut copies: Option<InternalPathCopies> = None;
         // Retrieve data computed in a previous iteration
         let p1_copies = match p1 {
             NULL_REVISION => None,
@@ -412,26 +402,8 @@
             ), // will be None if the vertex is not to be traversed
         };
         // combine it with data for that revision
-        let p1_copies = match p1_copies {
-            None => None,
-            Some(parent_copies) => Some(add_from_changes(
-                &mut path_map,
-                &parent_copies,
-                &changes,
-                Parent::FirstParent,
-                rev,
-            )),
-        };
-        let p2_copies = match p2_copies {
-            None => None,
-            Some(parent_copies) => Some(add_from_changes(
-                &mut path_map,
-                &parent_copies,
-                &changes,
-                Parent::SecondParent,
-                rev,
-            )),
-        };
+        let (p1_copies, p2_copies) =
+            chain_changes(&mut path_map, p1_copies, p2_copies, &changes, rev);
         let copies = match (p1_copies, p2_copies) {
             (None, None) => None,
             (c, None) => c,
@@ -489,5 +461,5 @@
 
 /// Combine ChangedFiles with some existing PathCopies information and return
 /// the result
-fn add_from_changes(
+fn chain_changes(
     path_map: &mut TwoWayPathMap,
@@ -493,3 +465,4 @@
     path_map: &mut TwoWayPathMap,
-    base_copies: &InternalPathCopies,
+    base_p1_copies: Option<InternalPathCopies>,
+    base_p2_copies: Option<InternalPathCopies>,
     changes: &ChangedFiles,
@@ -495,3 +468,2 @@
     changes: &ChangedFiles,
-    parent: Parent,
     current_rev: Revision,
@@ -497,6 +469,12 @@
     current_rev: Revision,
-) -> InternalPathCopies {
-    let mut copies = base_copies.clone();
+) -> (Option<InternalPathCopies>, Option<InternalPathCopies>) {
+    // Fast path the "nothing to do" case.
+    if let (None, None) = (&base_p1_copies, &base_p2_copies) {
+        return (None, None);
+    }
+
+    let mut p1_copies = base_p1_copies.clone();
+    let mut p2_copies = base_p2_copies.clone();
     for action in changes.iter_actions() {
         match action {
             Action::CopiedFromP1(path_dest, path_source) => {
@@ -500,8 +478,8 @@
     for action in changes.iter_actions() {
         match action {
             Action::CopiedFromP1(path_dest, path_source) => {
-                match parent {
-                    _ => (), // not the parent we are looking for
-                    Parent::FirstParent => add_one_copy(
+                match &mut p1_copies {
+                    None => (), // This is not a vertex we should proceed.
+                    Some(copies) => add_one_copy(
                         current_rev,
                         path_map,
@@ -506,7 +484,7 @@
                         current_rev,
                         path_map,
-                        &mut copies,
-                        &base_copies,
+                        copies,
+                        base_p1_copies.as_ref().unwrap(),
                         path_dest,
                         path_source,
                     ),
@@ -510,6 +488,6 @@
                         path_dest,
                         path_source,
                     ),
-                };
+                }
             }
             Action::CopiedFromP2(path_dest, path_source) => {
@@ -514,7 +492,7 @@
             }
             Action::CopiedFromP2(path_dest, path_source) => {
-                match parent {
-                    _ => (), //not the parent we are looking for
-                    Parent::SecondParent => add_one_copy(
+                match &mut p2_copies {
+                    None => (), // This is not a vertex we should proceed.
+                    Some(copies) => add_one_copy(
                         current_rev,
                         path_map,
@@ -519,7 +497,7 @@
                         current_rev,
                         path_map,
-                        &mut copies,
-                        &base_copies,
+                        copies,
+                        base_p2_copies.as_ref().unwrap(),
                         path_dest,
                         path_source,
                     ),
@@ -523,7 +501,7 @@
                         path_dest,
                         path_source,
                     ),
-                };
+                }
             }
             Action::Removed(deleted_path) => {
                 // We must drop copy information for removed file.
@@ -532,9 +510,22 @@
                 // propagate this information when merging two
                 // InternalPathCopies object.
                 let deleted = path_map.tokenize(deleted_path);
-                copies.entry(deleted).and_modify(|old| {
-                    old.mark_delete(current_rev);
-                });
+                match &mut p1_copies {
+                    None => (),
+                    Some(copies) => {
+                        copies.entry(deleted).and_modify(|old| {
+                            old.mark_delete(current_rev);
+                        });
+                    }
+                };
+                match &mut p2_copies {
+                    None => (),
+                    Some(copies) => {
+                        copies.entry(deleted).and_modify(|old| {
+                            old.mark_delete(current_rev);
+                        });
+                    }
+                };
             }
         }
     }
@@ -538,7 +529,7 @@
             }
         }
     }
-    copies
+    (p1_copies, p2_copies)
 }
 
 // insert one new copy information in an InternalPathCopies