diff --git a/rust/hg-core/src/copy_tracing.rs b/rust/hg-core/src/copy_tracing.rs
index e4384b8f4858e129bd2f9b7702fb8a669e881d62_cnVzdC9oZy1jb3JlL3NyYy9jb3B5X3RyYWNpbmcucnM=..bb731461b4c96eae26db66e9e4ca3c810c036c63_cnVzdC9oZy1jb3JlL3NyYy9jb3B5X3RyYWNpbmcucnM= 100644
--- a/rust/hg-core/src/copy_tracing.rs
+++ b/rust/hg-core/src/copy_tracing.rs
@@ -47,6 +47,19 @@
     Copied(&'a HgPath, &'a HgPath),
 }
 
+/// This express the possible "special" case we can get in a merge
+///
+/// See mercurial/metadata.py for details on these values.
+#[derive(PartialEq)]
+enum MergeCase {
+    /// Merged: file had history on both side that needed to be merged
+    Merged,
+    /// Salvaged: file was candidate for deletion, but survived the merge
+    Salvaged,
+    /// Normal: Not one of the two cases above
+    Normal,
+}
+
 impl ChangedFiles {
     pub fn new(
         removed: HashSet<HgPathBuf>,
@@ -86,6 +99,17 @@
         let remove_iter = remove_iter.map(|x| Action::Removed(x));
         copies_iter.chain(remove_iter)
     }
+
+    /// return the MergeCase value associated with a filename
+    fn get_merge_case(&self, path: &HgPath) -> MergeCase {
+        if self.salvaged.contains(path) {
+            return MergeCase::Salvaged;
+        } else if self.merged.contains(path) {
+            return MergeCase::Merged;
+        } else {
+            return MergeCase::Normal;
+        }
+    }
 }
 
 /// A struct responsible for answering "is X ancestors of Y" quickly
@@ -318,4 +342,5 @@
                     // same rev. So this is the same value.
                     unreachable!();
                 } else {
+                    let action = changes.get_merge_case(&dest);
                     if src_major.path.is_none()
@@ -321,7 +346,7 @@
                     if src_major.path.is_none()
-                        && changes.salvaged.contains(dest)
+                        && action == MergeCase::Salvaged
                     {
                         // If the file is "deleted" in the major side but was
                         // salvaged by the merge, we keep the minor side alive
                         pick_minor();
                     } else if src_minor.path.is_none()
@@ -323,11 +348,11 @@
                     {
                         // If the file is "deleted" in the major side but was
                         // salvaged by the merge, we keep the minor side alive
                         pick_minor();
                     } else if src_minor.path.is_none()
-                        && changes.salvaged.contains(dest)
+                        && action == MergeCase::Salvaged
                     {
                         // If the file is "deleted" in the minor side but was
                         // salvaged by the merge, unconditionnaly preserve the
                         // major side.
                         pick_major();
@@ -329,9 +354,9 @@
                     {
                         // If the file is "deleted" in the minor side but was
                         // salvaged by the merge, unconditionnaly preserve the
                         // major side.
                         pick_major();
-                    } else if changes.merged.contains(dest) {
+                    } else if action == MergeCase::Merged {
                         // If the file was actively merged, copy information
                         // from each side might conflict.  The major side will
                         // win such conflict.