diff --git a/mercurial/commit.py b/mercurial/commit.py --- a/mercurial/commit.py +++ b/mercurial/commit.py @@ -332,9 +332,20 @@ ): fparent1, fparent2 = fparent2, nullid + force_new_node = False + # The file might have been deleted by merge code and user explicitly choose + # to revert the file and keep it. The other case can be where there is + # change-delete or delete-change conflict and user explicitly choose to keep + # the file. The goal is to create a new filenode for users explicit choices + if ( + repo.ui.configbool(b'experimental', b'merge-track-undeleted') + and ms.active() + and ms.extras(fname).get(b'MERGE_DELETE_CANDIDATE') == b'yes' + ): + force_new_node = True # is the file changed? text = fctx.data() - if fparent2 != nullid or meta or flog.cmp(fparent1, text): + if fparent2 != nullid or meta or flog.cmp(fparent1, text) or force_new_node: if touched is None: # do not overwrite added touched = 'modified' fnode = flog.add(text, meta, tr, linkrev, fparent1, fparent2) diff --git a/tests/test-merge-combination.t b/tests/test-merge-combination.t --- a/tests/test-merge-combination.t +++ b/tests/test-merge-combination.t @@ -113,7 +113,7 @@ 1234 C: agree on "a" 123- C: agree on "a" 12-1 C: agree on "a" - 12-2 C: hg said "", expected "a" + 12-2 C: agree on "a" 12-3 C: agree on "a" 12-- C: agree on "a" 1-11 : hg said "", expected "a" diff --git a/tests/test-merge-criss-cross.t b/tests/test-merge-criss-cross.t --- a/tests/test-merge-criss-cross.t +++ b/tests/test-merge-criss-cross.t @@ -589,17 +589,14 @@ other-file the-file -XXX: This should create a new filenode because user explicitly decided to keep -the file. If we reuse the same filenode, future merges (criss-cross ones mostly) -will think that file remain unchanged and user explicit choice will not be taken -in consideration. $ hg debugrevlogindex the-file rev linkrev nodeid p1 p2 0 0 4b69178b9bda 000000000000 000000000000 1 1 59e363a07dc8 4b69178b9bda 000000000000 + 2 5 885af55420b3 59e363a07dc8 000000000000 $ hg update 'desc("updating-both-file")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("delete-the-file")' -t :local 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) @@ -626,11 +623,12 @@ rev linkrev nodeid p1 p2 0 0 4b69178b9bda 000000000000 000000000000 1 1 59e363a07dc8 4b69178b9bda 000000000000 + 2 5 885af55420b3 59e363a07dc8 000000000000 $ hg log -G -T '{node|short} {desc}\n' @ 5e3eccec60d8 merge-keeping-the-file-from-updated |\ - +---o e9b708131723 merge-keeping-the-file-from-deleted + +---o 38a4c3e7cac8 merge-keeping-the-file-from-deleted | |/ +---o a4e0e44229dc merge-deleting-the-file-from-updated | |/ @@ -662,16 +660,17 @@ $ hg update --clean 'desc("merge-deleting-the-file-from-deleted")' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("merge-keeping-the-file-from-deleted")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ ls -1 other-file + the-file (merging a deletion with keeping → conflict) BROKEN: this should result in conflict $ hg update --clean 'desc("merge-deleting-the-file-from-deleted")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg merge 'desc("merge-keeping-the-file-from-updated")' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) @@ -694,16 +693,17 @@ $ hg update --clean 'desc("merge-deleting-the-file-from-updated")' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("merge-keeping-the-file-from-deleted")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ ls -1 other-file + the-file (merging a deletion with keeping → conflict) BROKEN: this should result in conflict $ hg update --clean 'desc("merge-deleting-the-file-from-updated")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg merge 'desc("merge-keeping-the-file-from-updated")' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) @@ -715,7 +715,7 @@ $ hg update --clean 'desc("merge-keeping-the-file-from-updated")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("merge-keeping-the-file-from-deleted")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ ls -1 other-file @@ -725,7 +725,7 @@ BROKEN: this should result in conflict $ hg update --clean 'desc("merge-keeping-the-file-from-updated")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("merge-deleted-the-file-from-deleted")' abort: empty revision set [255] @@ -748,7 +748,7 @@ (merging two "keeping" together → no conflict) $ hg update --clean 'desc("merge-keeping-the-file-from-deleted")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("merge-keeping-the-file-from-updated")' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit)