diff --git a/mercurial/copies.py b/mercurial/copies.py
index 193ab7823d12f0dc9380d0e829631a8fabf2f992_bWVyY3VyaWFsL2NvcGllcy5weQ==..f6f2927bc389bc5e9d26ee26873b960770f59512_bWVyY3VyaWFsL2NvcGllcy5weQ== 100644
--- a/mercurial/copies.py
+++ b/mercurial/copies.py
@@ -427,7 +427,11 @@
                     # potential filelog related behavior.
                     assert parent == 2
                     current_copies = _merge_copies_dict(
-                        newcopies, current_copies, isancestor, changes
+                        newcopies,
+                        current_copies,
+                        isancestor,
+                        changes,
+                        current_rev,
                     )
             all_copies[current_rev] = current_copies
 
@@ -449,7 +453,7 @@
 PICK_EITHER = 2
 
 
-def _merge_copies_dict(minor, major, isancestor, changes):
+def _merge_copies_dict(minor, major, isancestor, changes, current_merge):
     """merge two copies-mapping together, minor and major
 
     In case of conflict, value from "major" will be picked.
@@ -467,8 +471,15 @@
         if other is None:
             minor[dest] = value
         else:
-            pick = _compare_values(changes, isancestor, dest, other, value)
-            if pick == PICK_MAJOR:
+            pick, overwrite = _compare_values(
+                changes, isancestor, dest, other, value
+            )
+            if overwrite:
+                if pick == PICK_MAJOR:
+                    minor[dest] = (current_merge, value[1])
+                else:
+                    minor[dest] = (current_merge, other[1])
+            elif pick == PICK_MAJOR:
                 minor[dest] = value
     return minor
 
@@ -476,6 +487,6 @@
 def _compare_values(changes, isancestor, dest, minor, major):
     """compare two value within a _merge_copies_dict loop iteration
 
-    return pick
+    return (pick, overwrite).
 
     - pick is one of PICK_MINOR, PICK_MAJOR or PICK_EITHER
@@ -480,5 +491,6 @@
 
     - pick is one of PICK_MINOR, PICK_MAJOR or PICK_EITHER
+    - overwrite is True if pick is a return of an ambiguity that needs resolution.
     """
     major_tt, major_value = major
     minor_tt, minor_value = minor
@@ -486,7 +498,7 @@
     if major_tt == minor_tt:
         # if it comes from the same revision it must be the same value
         assert major_value == minor_value
-        return PICK_EITHER
+        return PICK_EITHER, False
     elif (
         changes is not None
         and minor_value is not None
@@ -495,7 +507,7 @@
     ):
         # In this case, a deletion was reverted, the "alive" value overwrite
         # the deleted one.
-        return PICK_MINOR
+        return PICK_MINOR, True
     elif (
         changes is not None
         and major_value is not None
@@ -504,8 +516,8 @@
     ):
         # In this case, a deletion was reverted, the "alive" value overwrite
         # the deleted one.
-        return PICK_MAJOR
+        return PICK_MAJOR, True
     elif isancestor(minor_tt, major_tt):
         if changes is not None and dest in changes.merged:
             # change to dest happened on the branch without copy-source change,
             # so both source are valid and "major" wins.
@@ -508,6 +520,6 @@
     elif isancestor(minor_tt, major_tt):
         if changes is not None and dest in changes.merged:
             # change to dest happened on the branch without copy-source change,
             # so both source are valid and "major" wins.
-            return PICK_MAJOR
+            return PICK_MAJOR, True
         else:
@@ -513,6 +525,6 @@
         else:
-            return PICK_MAJOR
+            return PICK_MAJOR, False
     elif isancestor(major_tt, minor_tt):
         if changes is not None and dest in changes.merged:
             # change to dest happened on the branch without copy-source change,
             # so both source are valid and "major" wins.
@@ -515,6 +527,6 @@
     elif isancestor(major_tt, minor_tt):
         if changes is not None and dest in changes.merged:
             # change to dest happened on the branch without copy-source change,
             # so both source are valid and "major" wins.
-            return PICK_MAJOR
+            return PICK_MAJOR, True
         else:
@@ -520,4 +532,4 @@
         else:
-            return PICK_MINOR
+            return PICK_MINOR, False
     elif minor_value is None:
         # in case of conflict, the "alive" side wins.
@@ -522,5 +534,5 @@
     elif minor_value is None:
         # in case of conflict, the "alive" side wins.
-        return PICK_MAJOR
+        return PICK_MAJOR, True
     elif major_value is None:
         # in case of conflict, the "alive" side wins.
@@ -525,5 +537,5 @@
     elif major_value is None:
         # in case of conflict, the "alive" side wins.
-        return PICK_MINOR
+        return PICK_MINOR, True
     else:
         # in case of conflict where both side are alive, major wins.
@@ -528,6 +540,6 @@
     else:
         # in case of conflict where both side are alive, major wins.
-        return PICK_MAJOR
+        return PICK_MAJOR, True
 
 
 def _revinfo_getter_extra(repo):
diff --git a/rust/hg-core/src/copy_tracing.rs b/rust/hg-core/src/copy_tracing.rs
index 193ab7823d12f0dc9380d0e829631a8fabf2f992_cnVzdC9oZy1jb3JlL3NyYy9jb3B5X3RyYWNpbmcucnM=..f6f2927bc389bc5e9d26ee26873b960770f59512_cnVzdC9oZy1jb3JlL3NyYy9jb3B5X3RyYWNpbmcucnM= 100644
--- a/rust/hg-core/src/copy_tracing.rs
+++ b/rust/hg-core/src/copy_tracing.rs
@@ -568,20 +568,20 @@
     // This closure exist as temporary help while multiple developper are
     // actively working on this code. Feel free to re-inline it once this
     // code is more settled.
-    let mut cmp_value =
-        |dest: &PathToken,
-         src_minor: &TimeStampedPathCopy,
-         src_major: &TimeStampedPathCopy| {
-            compare_value(
-                path_map,
-                current_merge,
-                changes,
-                oracle,
-                dest,
-                src_minor,
-                src_major,
-            )
-        };
+    let cmp_value = |oracle: &mut AncestorOracle<A>,
+                     dest: &PathToken,
+                     src_minor: &TimeStampedPathCopy,
+                     src_major: &TimeStampedPathCopy| {
+        compare_value(
+            path_map,
+            current_merge,
+            changes,
+            oracle,
+            dest,
+            src_minor,
+            src_major,
+        )
+    };
     if minor.is_empty() {
         major
     } else if major.is_empty() {
@@ -605,5 +605,7 @@
         for (dest, src_minor) in minor {
             let src_major = major.get(&dest);
             match src_major {
-                None => major.insert(dest, src_minor),
+                None => {
+                    major.insert(dest, src_minor);
+                }
                 Some(src_major) => {
@@ -609,7 +611,24 @@
                 Some(src_major) => {
-                    match cmp_value(&dest, &src_minor, src_major) {
-                        MergePick::Any | MergePick::Major => None,
-                        MergePick::Minor => major.insert(dest, src_minor),
+                    let (pick, overwrite) =
+                        cmp_value(oracle, &dest, &src_minor, src_major);
+                    if overwrite {
+                        oracle.record_overwrite(src_minor.rev, current_merge);
+                        oracle.record_overwrite(src_major.rev, current_merge);
+                        let path = match pick {
+                            MergePick::Major => src_major.path,
+                            MergePick::Minor => src_minor.path,
+                            MergePick::Any => src_major.path,
+                        };
+                        let src = TimeStampedPathCopy {
+                            rev: current_merge,
+                            path,
+                        };
+                        major.insert(dest, src);
+                    } else {
+                        match pick {
+                            MergePick::Any | MergePick::Major => None,
+                            MergePick::Minor => major.insert(dest, src_minor),
+                        };
                     }
                 }
             };
@@ -621,5 +640,7 @@
         for (dest, src_major) in major {
             let src_minor = minor.get(&dest);
             match src_minor {
-                None => minor.insert(dest, src_major),
+                None => {
+                    minor.insert(dest, src_major);
+                }
                 Some(src_minor) => {
@@ -625,7 +646,24 @@
                 Some(src_minor) => {
-                    match cmp_value(&dest, src_minor, &src_major) {
-                        MergePick::Any | MergePick::Minor => None,
-                        MergePick::Major => minor.insert(dest, src_major),
+                    let (pick, overwrite) =
+                        cmp_value(oracle, &dest, &src_major, src_minor);
+                    if overwrite {
+                        oracle.record_overwrite(src_minor.rev, current_merge);
+                        oracle.record_overwrite(src_major.rev, current_merge);
+                        let path = match pick {
+                            MergePick::Major => src_minor.path,
+                            MergePick::Minor => src_major.path,
+                            MergePick::Any => src_major.path,
+                        };
+                        let src = TimeStampedPathCopy {
+                            rev: current_merge,
+                            path,
+                        };
+                        minor.insert(dest, src);
+                    } else {
+                        match pick {
+                            MergePick::Any | MergePick::Major => None,
+                            MergePick::Minor => minor.insert(dest, src_major),
+                        };
                     }
                 }
             };
@@ -663,12 +701,32 @@
                 DiffItem::Update { old, new } => {
                     let (dest, src_major) = new;
                     let (_, src_minor) = old;
-                    match cmp_value(dest, src_minor, src_major) {
-                        MergePick::Major => to_minor(dest, src_major),
-                        MergePick::Minor => to_major(dest, src_minor),
-                        // If the two entry are identical, no need to do
-                        // anything (but diff should not have yield them)
-                        MergePick::Any => unreachable!(),
+                    let (pick, overwrite) =
+                        cmp_value(oracle, dest, src_minor, src_major);
+                    if overwrite {
+                        oracle.record_overwrite(src_minor.rev, current_merge);
+                        oracle.record_overwrite(src_major.rev, current_merge);
+                        let path = match pick {
+                            MergePick::Major => src_major.path,
+                            MergePick::Minor => src_minor.path,
+                            // If the two entry are identical, no need to do
+                            // anything (but diff should not have yield them)
+                            MergePick::Any => src_major.path,
+                        };
+                        let src = TimeStampedPathCopy {
+                            rev: current_merge,
+                            path,
+                        };
+                        to_minor(dest, &src);
+                        to_major(dest, &src);
+                    } else {
+                        match pick {
+                            MergePick::Major => to_minor(dest, src_major),
+                            MergePick::Minor => to_major(dest, src_minor),
+                            // If the two entry are identical, no need to do
+                            // anything (but diff should not have yield them)
+                            MergePick::Any => unreachable!(),
+                        }
                     }
                 }
             };
@@ -717,10 +775,10 @@
     dest: &PathToken,
     src_minor: &TimeStampedPathCopy,
     src_major: &TimeStampedPathCopy,
-) -> MergePick {
+) -> (MergePick, bool) {
     if src_major.rev == current_merge {
         if src_minor.rev == current_merge {
             if src_major.path.is_none() {
                 // We cannot get different copy information for both p1 and p2
                 // from the same revision. Unless this was a
                 // deletion
@@ -721,13 +779,13 @@
     if src_major.rev == current_merge {
         if src_minor.rev == current_merge {
             if src_major.path.is_none() {
                 // We cannot get different copy information for both p1 and p2
                 // from the same revision. Unless this was a
                 // deletion
-                MergePick::Any
+                (MergePick::Any, false)
             } else {
                 unreachable!();
             }
         } else {
             // The last value comes the current merge, this value -will- win
             // eventually.
@@ -728,12 +786,11 @@
             } else {
                 unreachable!();
             }
         } else {
             // The last value comes the current merge, this value -will- win
             // eventually.
-            oracle.record_overwrite(src_minor.rev, src_major.rev);
-            MergePick::Major
+            (MergePick::Major, true)
         }
     } else if src_minor.rev == current_merge {
         // The last value comes the current merge, this value -will- win
         // eventually.
@@ -736,10 +793,9 @@
         }
     } else if src_minor.rev == current_merge {
         // The last value comes the current merge, this value -will- win
         // eventually.
-        oracle.record_overwrite(src_major.rev, src_minor.rev);
-        MergePick::Minor
+        (MergePick::Minor, true)
     } else if src_major.path == src_minor.path {
         // we have the same value, but from other source;
         if src_major.rev == src_minor.rev {
             // If the two entry are identical, they are both valid
@@ -742,6 +798,6 @@
     } else if src_major.path == src_minor.path {
         // we have the same value, but from other source;
         if src_major.rev == src_minor.rev {
             // If the two entry are identical, they are both valid
-            MergePick::Any
+            (MergePick::Any, false)
         } else if oracle.is_overwrite(src_major.rev, src_minor.rev) {
@@ -747,3 +803,3 @@
         } else if oracle.is_overwrite(src_major.rev, src_minor.rev) {
-            MergePick::Minor
+            (MergePick::Minor, false)
         } else if oracle.is_overwrite(src_minor.rev, src_major.rev) {
@@ -749,3 +805,3 @@
         } else if oracle.is_overwrite(src_minor.rev, src_major.rev) {
-            MergePick::Major
+            (MergePick::Major, false)
         } else {
@@ -751,5 +807,5 @@
         } else {
-            MergePick::Major
+            (MergePick::Any, true)
         }
     } else if src_major.rev == src_minor.rev {
         // We cannot get copy information for both p1 and p2 in the
@@ -766,7 +822,7 @@
         {
             // If the file is "deleted" in the major side but was
             // salvaged by the merge, we keep the minor side alive
-            MergePick::Minor
+            (MergePick::Minor, true)
         } else if src_major.path.is_some()
             && src_minor.path.is_none()
             && action == MergeCase::Salvaged
@@ -774,7 +830,7 @@
             // If the file is "deleted" in the minor side but was
             // salvaged by the merge, unconditionnaly preserve the
             // major side.
-            MergePick::Major
+            (MergePick::Major, true)
         } else if oracle.is_overwrite(src_minor.rev, src_major.rev) {
             // The information from the minor version are strictly older than
             // the major version
@@ -784,6 +840,6 @@
                 // mean the older copy information are still relevant.
                 //
                 // The major side wins such conflict.
-                MergePick::Major
+                (MergePick::Major, true)
             } else {
                 // No activity on the minor branch, pick the newer one.
@@ -788,6 +844,6 @@
             } else {
                 // No activity on the minor branch, pick the newer one.
-                MergePick::Major
+                (MergePick::Major, false)
             }
         } else if oracle.is_overwrite(src_major.rev, src_minor.rev) {
             if action == MergeCase::Merged {
@@ -796,6 +852,6 @@
                 // mean the older copy information are still relevant.
                 //
                 // The major side wins such conflict.
-                MergePick::Major
+                (MergePick::Major, true)
             } else {
                 // No activity on the minor branch, pick the newer one.
@@ -800,6 +856,6 @@
             } else {
                 // No activity on the minor branch, pick the newer one.
-                MergePick::Minor
+                (MergePick::Minor, false)
             }
         } else if src_minor.path.is_none() {
             // the minor side has no relevant information, pick the alive one
@@ -803,6 +859,6 @@
             }
         } else if src_minor.path.is_none() {
             // the minor side has no relevant information, pick the alive one
-            MergePick::Major
+            (MergePick::Major, true)
         } else if src_major.path.is_none() {
             // the major side has no relevant information, pick the alive one
@@ -807,5 +863,5 @@
         } else if src_major.path.is_none() {
             // the major side has no relevant information, pick the alive one
-            MergePick::Minor
+            (MergePick::Minor, true)
         } else {
             // by default the major side wins
@@ -810,6 +866,6 @@
         } else {
             // by default the major side wins
-            MergePick::Major
+            (MergePick::Major, true)
         }
     }
 }
diff --git a/tests/test-copies-chain-merge.t b/tests/test-copies-chain-merge.t
index 193ab7823d12f0dc9380d0e829631a8fabf2f992_dGVzdHMvdGVzdC1jb3BpZXMtY2hhaW4tbWVyZ2UudA==..f6f2927bc389bc5e9d26ee26873b960770f59512_dGVzdHMvdGVzdC1jb3BpZXMtY2hhaW4tbWVyZ2UudA== 100644
--- a/tests/test-copies-chain-merge.t
+++ b/tests/test-copies-chain-merge.t
@@ -2144,10 +2144,8 @@
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mK,AEm")' f
   A f
     a (filelog !)
-    a (missing-correct-output sidedata !)
-    a (missing-correct-output upgraded !)
-    b (known-bad-output sidedata !)
-    b (known-bad-output upgraded !)
+    a (sidedata !)
+    a (upgraded !)
 
 
 The result from mEAm is the same for the subsequent merge:
@@ -2167,10 +2165,8 @@
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mJ,EAm")' f
   A f
     a (filelog !)
-    b (missing-correct-output sidedata !)
-    b (missing-correct-output upgraded !)
-    a (known-bad-output sidedata !)
-    a (known-bad-output upgraded !)
+    b (sidedata !)
+    b (upgraded !)
 
 
 Subcase: chaining salvage information during a merge
@@ -2184,10 +2180,8 @@
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCB-revert-m-0")'
   M b
   A d
-    a (filelog !)
-    a (sidedata !)
-    a (upgraded !)
+    a (no-changeset no-compatibility !)
   R a
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBC-revert-m-0")'
   M b
   A d
@@ -2190,10 +2184,8 @@
   R a
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBC-revert-m-0")'
   M b
   A d
-    a (filelog !)
-    a (sidedata !)
-    a (upgraded !)
+    a (no-changeset no-compatibility !)
   R a
 
 chained output
@@ -2197,7 +2189,6 @@
   R a
 
 chained output
-
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBC+revert,Lm")'
   M b
   A d
@@ -2201,11 +2192,9 @@
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBC+revert,Lm")'
   M b
   A d
-    a (filelog !)
-    a (missing-correct-output sidedata !)
-    a (missing-correct-output upgraded !)
+    a (no-changeset no-compatibility !)
   A unrelated-l
   R a
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCB+revert,Lm")'
   M b
   A d
@@ -2207,13 +2196,11 @@
   A unrelated-l
   R a
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCB+revert,Lm")'
   M b
   A d
-    a (filelog !)
-    a (missing-correct-output sidedata !)
-    a (missing-correct-output upgraded !)
+    a (no-changeset no-compatibility !)
   A unrelated-l
   R a
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mL,BC+revertm")'
   M b
   A d
@@ -2215,13 +2202,11 @@
   A unrelated-l
   R a
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mL,BC+revertm")'
   M b
   A d
-    a (filelog !)
-    a (missing-correct-output sidedata !)
-    a (missing-correct-output upgraded !)
+    a (no-changeset no-compatibility !)
   A unrelated-l
   R a
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mL,CB+revertm")'
   M b
   A d
@@ -2223,11 +2208,9 @@
   A unrelated-l
   R a
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mL,CB+revertm")'
   M b
   A d
-    a (filelog !)
-    a (missing-correct-output sidedata !)
-    a (missing-correct-output upgraded !)
+    a (no-changeset no-compatibility !)
   A unrelated-l
   R a
 
@@ -2268,10 +2251,6 @@
 
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGF,Nm")' d
   A d
-    a (filelog !)
-    a (missing-correct-output sidedata !)
-    a (missing-correct-output upgraded !)
-    h (known-bad-output sidedata !)
-    h (known-bad-output upgraded !)
+    a (no-changeset no-compatibility !)
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mN,GFm")' d
   A d
@@ -2276,7 +2255,3 @@
   $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mN,GFm")' d
   A d
-    a (filelog !)
-    a (missing-correct-output sidedata !)
-    a (missing-correct-output upgraded !)
-    h (known-bad-output sidedata !)
-    h (known-bad-output upgraded !)
+    a (no-changeset no-compatibility !)