Mercurial > hg
view tests/test-resolve.t @ 42044:bb271ec2fbfb
compression: introduce a `storage.revlog.zstd.level` configuration
This option control the zstd compression level used when compressing revlog
chunk. The usage of zstd for revlog compression has not graduated from
experimental yet, but we intend to fix that soon.
The option name for the compression level is more straight forward to pick, so
this changesets comes first. Having a dedicated option for each compression
engine is useful because they don't support the same range of values.
I ran the same measurement as for the zlib compression level (in the parent
changesets). The variation in repository size is stay mostly in the same (small)
range. The "read/write" performance see smallish variation, but are overall much
better than zlib. Write performance show the same tend of having better write
performance for when reaching high-end compression.
Again, we don't intend to change the default zstd compression level (currently:
3) in this series. However this is worth investigating in the future.
The Performance comparison of zlib vs zstd is quite impressive. The repository
size stay in the same range, but the performance are much better in all
situations.
Comparison summary
==================
We are looking at:
- performance range for zlib
- performance range for zstd
- comparison of default zstd (level-3) to default zlib (level 6)
- comparison of the slowest zstd time to the fastest zlib time
Read performance:
-----------------
| zlib | zstd | cmp | f2s
mercurial | 0.170159 - 0.189219 | 0.144127 - 0.149624 | 80% | 88%
pypy | 2.679217 - 2.768691 | 1.532317 - 1.705044 | 60% | 63%
netbeans | 122.477027 - 141.620281 | 72.996346 - 89.731560 | 58% | 73%
mozilla | 147.867662 - 170.572118 | 91.700995 - 105.853099 | 56% | 71%
Write performance:
------------------
| zlib | zstd | cmp | f2s
mercurial | 53.250304 - 56.2936129 | 40.877025 - 45.677286 | 75% | 86%
pypy | 460.721984 - 476.589918 | 270.545409 - 301.002219 | 63% | 65%
netbeans | 520.560316 - 715.930400 | 370.356311 - 428.329652 | 55% | 82%
mozilla | 739.803002 - 987.056093 | 505.152906 - 591.930683 | 57% | 80%
Raw data
--------
repo alg lvl .hg/store size 00manifest.d read write
mercurial zlib 1 49,402,813 5,963,475 0.170159 53.250304
mercurial zlib 6 47,197,397 5,875,730 0.182820 56.264320
mercurial zlib 9 47,121,596 5,849,781 0.189219 56.293612
mercurial zstd 1 49,737,084 5,966,355 0.144127 40.877025
mercurial zstd 3 48,961,867 5,895,208 0.146376 42.268142
mercurial zstd 5 48,200,592 5,938,676 0.149624 43.162875
mercurial zstd 10 47,833,520 5,913,353 0.145185 44.012489
mercurial zstd 15 47,314,604 5,728,679 0.147686 45.677286
mercurial zstd 20 47,330,502 5,830,539 0.145789 45.025407
mercurial zstd 22 47,330,076 5,830,539 0.143996 44.690460
pypy zlib 1 370,830,572 28,462,425 2.679217 460.721984
pypy zlib 6 340,112,317 27,648,747 2.768691 467.537158
pypy zlib 9 338,360,736 27,639,003 2.763495 476.589918
pypy zstd 1 362,377,479 27,916,214 1.532317 270.545409
pypy zstd 3 354,137,693 27,905,988 1.686718 294.951509
pypy zstd 5 342,640,043 27,655,774 1.705044 301.002219
pypy zstd 10 334,224,327 27,164,493 1.567287 285.186239
pypy zstd 15 329,000,363 26,645,965 1.637729 299.561332
pypy zstd 20 324,534,039 26,199,547 1.526813 302.149827
pypy zstd 22 324,530,595 26,198,932 1.525718 307.821218
netbeans zlib 1 1,281,847,810 165,495,457 122.477027 520.560316
netbeans zlib 6 1,205,284,353 159,161,207 139.876147 715.930400
netbeans zlib 9 1,197,135,671 155,034,586 141.620281 678.297064
netbeans zstd 1 1,259,581,737 160,840,613 72.996346 370.356311
netbeans zstd 3 1,232,978,122 157,691,551 81.622317 396.733087
netbeans zstd 5 1,208,034,075 160,246,880 83.080549 364.342626
netbeans zstd 10 1,188,624,176 156,083,417 79.323935 403.594602
netbeans zstd 15 1,176,973,589 153,859,477 89.731560 428.329652
netbeans zstd 20 1,162,958,258 151,147,535 82.842667 392.335349
netbeans zstd 22 1,162,707,029 151,150,220 82.565695 402.840655
mozilla zlib 1 2,775,497,186 298,527,987 147.867662 751.263721
mozilla zlib 6 2,596,856,420 286,597,671 170.572118 987.056093
mozilla zlib 9 2,587,542,494 287,018,264 163.622338 739.803002
mozilla zstd 1 2,723,159,348 286,617,532 91.700995 570.042751
mozilla zstd 3 2,665,055,001 286,152,013 95.240155 561.412805
mozilla zstd 5 2,607,819,817 288,060,030 101.978048 505.152906
mozilla zstd 10 2,558,761,085 283,967,648 104.113481 497.771202
mozilla zstd 15 2,526,216,060 275,581,300 105.853099 591.930683
mozilla zstd 20 2,485,114,806 266,478,859 95.268795 576.515389
mozilla zstd 22 2,484,869,080 266,456,505 94.429282 572.785537
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Wed, 27 Mar 2019 18:35:59 +0100 |
parents | 72a9aacff645 |
children | 4764e8436b2a |
line wrap: on
line source
test that a commit clears the merge state. $ hg init repo $ cd repo $ echo foo > file1 $ echo foo > file2 $ hg commit -Am 'add files' adding file1 adding file2 $ echo bar >> file1 $ echo bar >> file2 $ hg commit -Am 'append bar to files' create a second head with conflicting edits $ hg up -C 0 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ echo baz >> file1 $ echo baz >> file2 $ hg commit -Am 'append baz to files' created new head create a third head with no conflicting edits $ hg up -qC 0 $ echo foo > file3 $ hg commit -Am 'add non-conflicting file' adding file3 created new head failing merge $ hg up -qC 2 $ hg merge --tool=internal:fail 1 0 files updated, 0 files merged, 0 files removed, 2 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon [1] resolve -l should contain unresolved entries $ hg resolve -l U file1 U file2 $ hg resolve -l --no-status file1 file2 resolving an unknown path should emit a warning, but not for -l $ hg resolve -m does-not-exist arguments do not match paths that need resolving $ hg resolve -l does-not-exist tell users how they could have used resolve $ mkdir nested $ cd nested $ hg resolve -m file1 arguments do not match paths that need resolving (try: hg resolve -m path:file1) $ hg resolve -m file1 filez arguments do not match paths that need resolving (try: hg resolve -m path:file1 path:filez) $ hg resolve -m path:file1 path:filez $ hg resolve -l R file1 U file2 $ hg resolve -l --config ui.relative-paths=yes R ../file1 U ../file2 $ hg resolve --re-merge filez file2 arguments do not match paths that need resolving (try: hg resolve --re-merge path:filez path:file2) $ hg resolve -m filez file2 arguments do not match paths that need resolving (try: hg resolve -m path:filez path:file2) $ hg resolve -m path:filez path:file2 (no more unresolved files) $ hg resolve -l R file1 R file2 cleanup $ hg resolve -u $ cd .. $ rmdir nested don't allow marking or unmarking driver-resolved files $ cat > $TESTTMP/markdriver.py << EOF > '''mark and unmark files as driver-resolved''' > from mercurial import ( > merge, > pycompat, > registrar, > scmutil, > ) > cmdtable = {} > command = registrar.command(cmdtable) > @command(b'markdriver', > [(b'u', b'unmark', None, b'')], > b'FILE...') > def markdriver(ui, repo, *pats, **opts): > wlock = repo.wlock() > opts = pycompat.byteskwargs(opts) > try: > ms = merge.mergestate.read(repo) > m = scmutil.match(repo[None], pats, opts) > for f in ms: > if not m(f): > continue > if not opts[b'unmark']: > ms.mark(f, b'd') > else: > ms.mark(f, b'u') > ms.commit() > finally: > wlock.release() > EOF $ hg --config extensions.markdriver=$TESTTMP/markdriver.py markdriver file1 $ hg resolve --list D file1 U file2 $ hg resolve --mark file1 not marking file1 as it is driver-resolved this should not print out file1 $ hg resolve --mark --all (no more unresolved files -- run "hg resolve --all" to conclude) $ hg resolve --mark 'glob:file*' (no more unresolved files -- run "hg resolve --all" to conclude) $ hg resolve --list D file1 R file2 $ hg resolve --unmark file1 not unmarking file1 as it is driver-resolved (no more unresolved files -- run "hg resolve --all" to conclude) $ hg resolve --unmark --all $ hg resolve --list D file1 U file2 $ hg --config extensions.markdriver=$TESTTMP/markdriver.py markdriver --unmark file1 $ hg resolve --list U file1 U file2 resolve the failure $ echo resolved > file1 $ hg resolve -m file1 resolve -l should show resolved file as resolved $ hg resolve -l R file1 U file2 $ hg resolve -l -Tjson [ { "mergestatus": "R", "path": "file1" }, { "mergestatus": "U", "path": "file2" } ] $ hg resolve -l -T '{path} {mergestatus} {status} {p1rev} {p2rev}\n' file1 R M 2 1 file2 U M 2 1 resolve -m without paths should mark all resolved $ hg resolve -m (no more unresolved files) $ hg commit -m 'resolved' resolve -l should be empty after commit $ hg resolve -l $ hg resolve -l -Tjson [ ] resolve --all should abort when no merge in progress $ hg resolve --all abort: resolve command not applicable when not merging [255] resolve -m should abort when no merge in progress $ hg resolve -m abort: resolve command not applicable when not merging [255] can not update or merge when there are unresolved conflicts $ hg up -qC 0 $ echo quux >> file1 $ hg up 1 merging file1 warning: conflicts while merging file1! (edit, then use 'hg resolve --mark') 1 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges [1] $ hg up 0 abort: outstanding merge conflicts [255] $ hg merge 2 abort: outstanding merge conflicts [255] $ hg merge --force 2 abort: outstanding merge conflicts [255] set up conflict-free merge $ hg up -qC 3 $ hg merge 1 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) resolve --all should do nothing in merge without conflicts $ hg resolve --all (no more unresolved files) resolve -m should do nothing in merge without conflicts $ hg resolve -m (no more unresolved files) get back to conflicting state $ hg up -qC 2 $ hg merge --tool=internal:fail 1 0 files updated, 0 files merged, 0 files removed, 2 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon [1] resolve without arguments should suggest --all $ hg resolve abort: no files or directories specified (use --all to re-merge all unresolved files) [255] resolve --all should re-merge all unresolved files $ hg resolve --all merging file1 merging file2 warning: conflicts while merging file1! (edit, then use 'hg resolve --mark') warning: conflicts while merging file2! (edit, then use 'hg resolve --mark') [1] $ cat file1.orig foo baz $ cat file2.orig foo baz .orig files should exists where specified $ hg resolve --all --verbose --config 'ui.origbackuppath=.hg/origbackups' merging file1 creating directory: $TESTTMP/repo/.hg/origbackups merging file2 warning: conflicts while merging file1! (edit, then use 'hg resolve --mark') warning: conflicts while merging file2! (edit, then use 'hg resolve --mark') [1] $ ls .hg/origbackups file1 file2 $ grep '<<<' file1 > /dev/null $ grep '<<<' file2 > /dev/null resolve <file> should re-merge file $ echo resolved > file1 $ hg resolve -q file1 warning: conflicts while merging file1! (edit, then use 'hg resolve --mark') [1] $ grep '<<<' file1 > /dev/null test .orig behavior with resolve $ hg resolve -q file1 --tool "sh -c 'f --dump \"$TESTTMP/repo/file1.orig\"'" $TESTTMP/repo/file1.orig: >>> foo baz <<< resolve <file> should do nothing if 'file' was marked resolved $ echo resolved > file1 $ hg resolve -m file1 $ hg resolve -q file1 $ cat file1 resolved insert unsupported advisory merge record $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py fakemergerecord -x $ hg debugmergestate * version 2 records local: 57653b9f834a4493f7240b0681efcb9ae7cab745 other: dc77451844e37f03f5c559e3b8529b2b48d381d1 labels: local: working copy other: merge rev unrecognized entry: x advisory record file extras: file1 (ancestorlinknode = 99726c03216e233810a2564cbc0adfe395007eac) file: file1 (record type "F", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) local path: file1 (flags "") ancestor path: file1 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd) other path: file1 (node 6f4310b00b9a147241b071a60c28a650827fb03d) file extras: file2 (ancestorlinknode = 99726c03216e233810a2564cbc0adfe395007eac) file: file2 (record type "F", state "u", hash cb99b709a1978bd205ab9dfd4c5aaa1fc91c7523) local path: file2 (flags "") ancestor path: file2 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd) other path: file2 (node 6f4310b00b9a147241b071a60c28a650827fb03d) $ hg resolve -l R file1 U file2 insert unsupported mandatory merge record $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py fakemergerecord -X $ hg debugmergestate * version 2 records local: 57653b9f834a4493f7240b0681efcb9ae7cab745 other: dc77451844e37f03f5c559e3b8529b2b48d381d1 labels: local: working copy other: merge rev file extras: file1 (ancestorlinknode = 99726c03216e233810a2564cbc0adfe395007eac) file: file1 (record type "F", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) local path: file1 (flags "") ancestor path: file1 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd) other path: file1 (node 6f4310b00b9a147241b071a60c28a650827fb03d) file extras: file2 (ancestorlinknode = 99726c03216e233810a2564cbc0adfe395007eac) file: file2 (record type "F", state "u", hash cb99b709a1978bd205ab9dfd4c5aaa1fc91c7523) local path: file2 (flags "") ancestor path: file2 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd) other path: file2 (node 6f4310b00b9a147241b071a60c28a650827fb03d) unrecognized entry: X mandatory record $ hg resolve -l abort: unsupported merge state records: X (see https://mercurial-scm.org/wiki/MergeStateRecords for more information) [255] $ hg resolve -ma abort: unsupported merge state records: X (see https://mercurial-scm.org/wiki/MergeStateRecords for more information) [255] $ hg summary warning: merge state has unsupported record types: X parent: 2:57653b9f834a append baz to files parent: 1:dc77451844e3 append bar to files branch: default commit: 2 modified, 2 unknown (merge) update: 2 new changesets (update) phases: 5 draft update --clean shouldn't abort on unsupported records $ hg up -qC 1 $ hg debugmergestate no merge state found test crashed merge with empty mergestate $ mkdir .hg/merge $ touch .hg/merge/state resolve -l should be empty $ hg resolve -l resolve -m can be configured to look for remaining conflict markers $ hg up -qC 2 $ hg merge -q --tool=internal:merge 1 warning: conflicts while merging file1! (edit, then use 'hg resolve --mark') warning: conflicts while merging file2! (edit, then use 'hg resolve --mark') [1] $ hg resolve -l U file1 U file2 $ echo 'remove markers' > file1 $ hg --config commands.resolve.mark-check=abort resolve -m warning: the following files still have conflict markers: file2 abort: conflict markers detected (use --all to mark anyway) [255] $ hg resolve -l U file1 U file2 Try with --all from the hint $ hg --config commands.resolve.mark-check=abort resolve -m --all warning: the following files still have conflict markers: file2 (no more unresolved files) $ hg resolve -l R file1 R file2 Test option value 'warn' $ hg resolve --unmark $ hg resolve -l U file1 U file2 $ hg --config commands.resolve.mark-check=warn resolve -m warning: the following files still have conflict markers: file2 (no more unresolved files) $ hg resolve -l R file1 R file2 If the file is already marked as resolved, we don't warn about it $ hg resolve --unmark file1 $ hg resolve -l U file1 R file2 $ hg --config commands.resolve.mark-check=warn resolve -m (no more unresolved files) $ hg resolve -l R file1 R file2 If the user passes an invalid value, we treat it as 'none'. $ hg resolve --unmark $ hg resolve -l U file1 U file2 $ hg --config commands.resolve.mark-check=nope resolve -m (no more unresolved files) $ hg resolve -l R file1 R file2 Test explicitly setting the option to 'none' $ hg resolve --unmark $ hg resolve -l U file1 U file2 $ hg --config commands.resolve.mark-check=none resolve -m (no more unresolved files) $ hg resolve -l R file1 R file2 Test with marking an explicit file as resolved, this should not abort (since there's no --force flag, we have no way of combining --all with a filename) $ hg resolve --unmark $ hg resolve -l U file1 U file2 (This downgrades to a warning since an explicit file was specified). $ hg --config commands.resolve.mark-check=abort resolve -m file2 warning: the following files still have conflict markers: file2 $ hg resolve -l U file1 R file2 Testing the --re-merge flag $ hg resolve --unmark file1 $ hg resolve -l U file1 R file2 $ hg resolve --mark --re-merge abort: too many actions specified [255] $ hg resolve --re-merge --all merging file1 warning: conflicts while merging file1! (edit, then use 'hg resolve --mark') [1] Explicit re-merge $ hg resolve --unmark file1 $ hg resolve --config commands.resolve.explicit-re-merge=1 --all abort: no action specified (use --mark, --unmark, --list or --re-merge) [255] $ hg resolve --config commands.resolve.explicit-re-merge=1 --re-merge --all merging file1 warning: conflicts while merging file1! (edit, then use 'hg resolve --mark') [1] $ cd .. ====================================================== Test 'hg resolve' confirm config option functionality | ====================================================== $ cat >> $HGRCPATH << EOF > [extensions] > rebase= > EOF $ hg init repo2 $ cd repo2 $ echo boss > boss $ hg ci -Am "add boss" adding boss $ for emp in emp1 emp2 emp3; do echo work > $emp; done; $ hg ci -Aqm "added emp1 emp2 emp3" $ hg up 0 0 files updated, 0 files merged, 3 files removed, 0 files unresolved $ for emp in emp1 emp2 emp3; do echo nowork > $emp; done; $ hg ci -Aqm "added lazy emp1 emp2 emp3" $ hg log -GT "{rev} {node|short} {firstline(desc)}\n" @ 2 0acfd4a49af0 added lazy emp1 emp2 emp3 | | o 1 f30f98a8181f added emp1 emp2 emp3 |/ o 0 88660038d466 add boss $ hg rebase -s 1 -d 2 rebasing 1:f30f98a8181f "added emp1 emp2 emp3" merging emp1 merging emp2 merging emp3 warning: conflicts while merging emp1! (edit, then use 'hg resolve --mark') warning: conflicts while merging emp2! (edit, then use 'hg resolve --mark') warning: conflicts while merging emp3! (edit, then use 'hg resolve --mark') unresolved conflicts (see hg resolve, then hg rebase --continue) [1] Test when commands.resolve.confirm config option is not set: =========================================================== $ hg resolve --all merging emp1 merging emp2 merging emp3 warning: conflicts while merging emp1! (edit, then use 'hg resolve --mark') warning: conflicts while merging emp2! (edit, then use 'hg resolve --mark') warning: conflicts while merging emp3! (edit, then use 'hg resolve --mark') [1] Test when config option is set: ============================== $ cat >> .hg/hgrc << EOF > [ui] > interactive = True > [commands] > resolve.confirm = True > EOF $ hg resolve abort: no files or directories specified (use --all to re-merge all unresolved files) [255] $ hg resolve --all << EOF > n > EOF re-merge all unresolved files (yn)? n abort: user quit [255] $ hg resolve --all << EOF > y > EOF re-merge all unresolved files (yn)? y merging emp1 merging emp2 merging emp3 warning: conflicts while merging emp1! (edit, then use 'hg resolve --mark') warning: conflicts while merging emp2! (edit, then use 'hg resolve --mark') warning: conflicts while merging emp3! (edit, then use 'hg resolve --mark') [1] Test that commands.resolve.confirm respect --mark option (only when no patterns args are given): =============================================================================================== $ hg resolve -m emp1 $ hg resolve -l R emp1 U emp2 U emp3 $ hg resolve -m << EOF > n > EOF mark all unresolved files as resolved (yn)? n abort: user quit [255] $ hg resolve -m << EOF > y > EOF mark all unresolved files as resolved (yn)? y (no more unresolved files) continue: hg rebase --continue $ hg resolve -l R emp1 R emp2 R emp3 Test that commands.resolve.confirm respect --unmark option (only when no patterns args are given): ================================================================================================= $ hg resolve -u emp1 $ hg resolve -l U emp1 R emp2 R emp3 $ hg resolve -u << EOF > n > EOF mark all resolved files as unresolved (yn)? n abort: user quit [255] $ hg resolve -m << EOF > y > EOF mark all unresolved files as resolved (yn)? y (no more unresolved files) continue: hg rebase --continue $ hg resolve -l R emp1 R emp2 R emp3 $ hg rebase --abort rebase aborted Done with commands.resolve.confirm tests: $ cd .. Test that commands.resolve.mark-check works even if there are deleted files: $ hg init resolve-deleted $ cd resolve-deleted $ echo r0 > file1 $ hg ci -qAm r0 $ echo r1 > file1 $ hg ci -qm r1 $ hg co -qr 0 $ hg rm file1 $ hg ci -qm "r2 (delete file1)" (At this point we have r0 creating file1, and sibling commits r1 and r2, which modify and delete file1, respectively) $ hg merge -r 1 file 'file1' was deleted in local [working copy] but was modified in other [merge rev]. What do you want to do? use (c)hanged version, leave (d)eleted, or leave (u)nresolved? u 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon [1] $ hg resolve --list U file1 Because we left it as 'unresolved' the file should still exist. $ [ -f file1 ] || echo "File does not exist?" BC behavior: `hg resolve --mark` accepts that the file is still there, and doesn't have a problem with this situation. $ hg resolve --mark --config commands.resolve.mark-check=abort (no more unresolved files) $ hg resolve --list R file1 The file is still there: $ [ -f file1 ] || echo "File does not exist?" Let's check mark-check=warn: $ hg resolve --unmark file1 $ hg resolve --mark --config commands.resolve.mark-check=warn (no more unresolved files) $ hg resolve --list R file1 The file is still there: $ [ -f file1 ] || echo "File does not exist?" Let's resolve the issue by deleting the file via `hg resolve` $ hg resolve --unmark file1 $ echo 'd' | hg resolve file1 --config ui.interactive=1 file 'file1' was deleted in local [working copy] but was modified in other [merge rev]. What do you want to do? use (c)hanged version, leave (d)eleted, or leave (u)nresolved? d (no more unresolved files) $ hg resolve --list R file1 The file is deleted: $ [ -f file1 ] && echo "File still exists?" || true Doing `hg resolve --mark` doesn't break now that the file is missing: $ hg resolve --mark --config commands.resolve.mark-check=abort (no more unresolved files) $ hg resolve --mark --config commands.resolve.mark-check=warn (no more unresolved files) Resurrect the file, and delete it outside of hg: $ hg resolve --unmark file1 $ hg resolve file1 file 'file1' was deleted in local [working copy] but was modified in other [merge rev]. What do you want to do? use (c)hanged version, leave (d)eleted, or leave (u)nresolved? u [1] $ [ -f file1 ] || echo "File does not exist?" $ hg resolve --list U file1 $ rm file1 $ hg resolve --mark --config commands.resolve.mark-check=abort (no more unresolved files) $ hg resolve --list R file1 $ hg resolve --unmark file1 $ hg resolve file1 file 'file1' was deleted in local [working copy] but was modified in other [merge rev]. What do you want to do? use (c)hanged version, leave (d)eleted, or leave (u)nresolved? u [1] $ [ -f file1 ] || echo "File does not exist?" $ hg resolve --list U file1 $ rm file1 $ hg resolve --mark --config commands.resolve.mark-check=warn (no more unresolved files) $ hg resolve --list R file1 For completeness, let's try that in the opposite direction (merging r2 into r1, instead of r1 into r2): $ hg update -qCr 1 $ hg merge -r 2 file 'file1' was deleted in other [merge rev] but was modified in local [working copy]. What do you want to do? use (c)hanged version, (d)elete, or leave (u)nresolved? u 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon [1] $ hg resolve --list U file1 Because we left it as 'unresolved' the file should still exist. $ [ -f file1 ] || echo "File does not exist?" BC behavior: `hg resolve --mark` accepts that the file is still there, and doesn't have a problem with this situation. $ hg resolve --mark --config commands.resolve.mark-check=abort (no more unresolved files) $ hg resolve --list R file1 The file is still there: $ [ -f file1 ] || echo "File does not exist?" Let's check mark-check=warn: $ hg resolve --unmark file1 $ hg resolve --mark --config commands.resolve.mark-check=warn (no more unresolved files) $ hg resolve --list R file1 The file is still there: $ [ -f file1 ] || echo "File does not exist?" Let's resolve the issue by deleting the file via `hg resolve` $ hg resolve --unmark file1 $ echo 'd' | hg resolve file1 --config ui.interactive=1 file 'file1' was deleted in other [merge rev] but was modified in local [working copy]. What do you want to do? use (c)hanged version, (d)elete, or leave (u)nresolved? d (no more unresolved files) $ hg resolve --list R file1 The file is deleted: $ [ -f file1 ] && echo "File still exists?" || true Doing `hg resolve --mark` doesn't break now that the file is missing: $ hg resolve --mark --config commands.resolve.mark-check=abort (no more unresolved files) $ hg resolve --mark --config commands.resolve.mark-check=warn (no more unresolved files) Resurrect the file, and delete it outside of hg: $ hg resolve --unmark file1 $ hg resolve file1 file 'file1' was deleted in other [merge rev] but was modified in local [working copy]. What do you want to do? use (c)hanged version, (d)elete, or leave (u)nresolved? u [1] $ [ -f file1 ] || echo "File does not exist?" $ hg resolve --list U file1 $ rm file1 $ hg resolve --mark --config commands.resolve.mark-check=abort (no more unresolved files) $ hg resolve --list R file1 $ hg resolve --unmark file1 $ hg resolve file1 file 'file1' was deleted in other [merge rev] but was modified in local [working copy]. What do you want to do? use (c)hanged version, (d)elete, or leave (u)nresolved? u [1] $ [ -f file1 ] || echo "File does not exist?" $ hg resolve --list U file1 $ rm file1 $ hg resolve --mark --config commands.resolve.mark-check=warn (no more unresolved files) $ hg resolve --list R file1 $ cd ..