diff --git a/rust/hg-core/src/copy_tracing.rs b/rust/hg-core/src/copy_tracing.rs
index 46e63a17afbda73d7cef458d85fe8706dcf00cc3_cnVzdC9oZy1jb3JlL3NyYy9jb3B5X3RyYWNpbmcucnM=..a2aec3432948d748d2c9f06198255648f1ef347e_cnVzdC9oZy1jb3JlL3NyYy9jb3B5X3RyYWNpbmcucnM= 100644
--- a/rust/hg-core/src/copy_tracing.rs
+++ b/rust/hg-core/src/copy_tracing.rs
@@ -358,46 +358,8 @@
                 assert_eq!(rev, p2);
                 Parent::SecondParent
             };
-            let mut new_copies = copies.clone();
-
-            for action in changes.iter_actions(parent) {
-                match action {
-                    Action::Copied(dest, source) => {
-                        let entry;
-                        if let Some(v) = copies.get(source) {
-                            entry = match &v.path {
-                                Some(path) => Some((*(path)).to_owned()),
-                                None => Some(source.to_owned()),
-                            }
-                        } else {
-                            entry = Some(source.to_owned());
-                        }
-                        // Each new entry is introduced by the children, we
-                        // record this information as we will need it to take
-                        // the right decision when merging conflicting copy
-                        // information. See merge_copies_dict for details.
-                        let ttpc = TimeStampedPathCopy {
-                            rev: *child,
-                            path: entry,
-                        };
-                        new_copies.insert(dest.to_owned(), ttpc);
-                    }
-                    Action::Removed(f) => {
-                        // We must drop copy information for removed file.
-                        //
-                        // We need to explicitly record them as dropped to
-                        // propagate this information when merging two
-                        // TimeStampedPathCopies object.
-                        if new_copies.contains_key(f.as_ref()) {
-                            let ttpc = TimeStampedPathCopy {
-                                rev: *child,
-                                path: None,
-                            };
-                            new_copies.insert(f.to_owned(), ttpc);
-                        }
-                    }
-                }
-            }
+            let new_copies =
+                add_from_changes(&copies, &changes, parent, *child);
 
             // Merge has two parents needs to combines their copy information.
             //
@@ -437,6 +399,56 @@
     result
 }
 
+/// Combine ChangedFiles with some existing PathCopies information and return
+/// the result
+fn add_from_changes(
+    base_copies: &TimeStampedPathCopies,
+    changes: &ChangedFiles,
+    parent: Parent,
+    current_rev: Revision,
+) -> TimeStampedPathCopies {
+    let mut copies = base_copies.clone();
+    for action in changes.iter_actions(parent) {
+        match action {
+            Action::Copied(dest, source) => {
+                let entry;
+                if let Some(v) = base_copies.get(source) {
+                    entry = match &v.path {
+                        Some(path) => Some((*(path)).to_owned()),
+                        None => Some(source.to_owned()),
+                    }
+                } else {
+                    entry = Some(source.to_owned());
+                }
+                // Each new entry is introduced by the children, we
+                // record this information as we will need it to take
+                // the right decision when merging conflicting copy
+                // information. See merge_copies_dict for details.
+                let ttpc = TimeStampedPathCopy {
+                    rev: current_rev,
+                    path: entry,
+                };
+                copies.insert(dest.to_owned(), ttpc);
+            }
+            Action::Removed(f) => {
+                // We must drop copy information for removed file.
+                //
+                // We need to explicitly record them as dropped to
+                // propagate this information when merging two
+                // TimeStampedPathCopies object.
+                if copies.contains_key(f.as_ref()) {
+                    let ttpc = TimeStampedPathCopy {
+                        rev: current_rev,
+                        path: None,
+                    };
+                    copies.insert(f.to_owned(), ttpc);
+                }
+            }
+        }
+    }
+    copies
+}
+
 /// merge two copies-mapping together, minor and major
 ///
 /// In case of conflict, value from "major" will be picked, unless in some