Mercurial > hg
view tests/test-copies-chain-merge.t @ 44459:6f1f4a6f4168
copies-tests: add a case where a file is deleted/added but with a merge
This is a case similar to DB/BD, but in this case the other branch updated the
file. So an actual merge happens and the two "independant" file history has to
be merged.
Differential Revision: https://phab.mercurial-scm.org/D8241
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Tue, 03 Mar 2020 15:46:28 +0100 |
parents | 890def17d03b |
children | c8fd21413458 |
line wrap: on
line source
===================================================== Test Copy tracing for chain of copies involving merge ===================================================== This test files covers copies/rename case for a chains of commit where merges are involved. It cheks we do not have unwanted update of behavior and that the different options to retrieve copies behave correctly. Setup ===== use git diff to see rename $ cat << EOF >> $HGRCPATH > [diff] > git=yes > [ui] > logtemplate={rev} {desc}]\n > EOF $ hg init repo-chain $ cd repo-chain Add some linear rename initialy $ touch a b h $ hg ci -Am 'i-0 initial commit: a b h' adding a adding b adding h $ hg mv a c $ hg ci -Am 'i-1: a -move-> c' $ hg mv c d $ hg ci -Am 'i-2: c -move-> d' $ hg log -G @ 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h] And having another branch with renames on the other side $ hg mv d e $ hg ci -Am 'a-1: d -move-> e' $ hg mv e f $ hg ci -Am 'a-2: e -move-> f' $ hg log -G --rev '::.' @ 4 a-2: e -move-> f] | o 3 a-1: d -move-> e] | o 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h] Have a branching with nothing on one side $ hg up 'desc("i-2")' 1 files updated, 0 files merged, 1 files removed, 0 files unresolved $ echo foo > b $ hg ci -m 'b-1: b update' created new head $ hg log -G --rev '::.' @ 5 b-1: b update] | o 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h] Merge the two branches we just defined (in both directions) - one with change to an unrelated file - one with renames in them $ hg up 'desc("b-1")' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("a-2")' 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) $ hg ci -m 'mBAm-0 simple merge - one way' $ hg up 'desc("a-2")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("b-1")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ hg ci -m 'mABm-0 simple merge - the other way' created new head $ hg log -G --rev '::(desc("mABm")+desc("mBAm"))' @ 7 mABm-0 simple merge - the other way] |\ +---o 6 mBAm-0 simple merge - one way] | |/ | o 5 b-1: b update] | | o | 4 a-2: e -move-> f] | | o | 3 a-1: d -move-> e] |/ o 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h] Create a branch that delete a file previous renamed $ hg up 'desc("i-2")' 2 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg rm d $ hg ci -m 'c-1 delete d' created new head $ hg log -G --rev '::.' @ 8 c-1 delete d] | o 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h] Merge: - one with change to an unrelated file - one deleting the change and recreate an unrelated file after the merge $ hg up 'desc("b-1")' 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("c-1")' 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) $ hg ci -m 'mBCm-0 simple merge - one way' $ echo bar > d $ hg add d $ hg ci -m 'mBCm-1 re-add d' $ hg up 'desc("c-1")' 1 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg merge 'desc("b-1")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ hg ci -m 'mCBm-0 simple merge - the other way' created new head $ echo bar > d $ hg add d $ hg ci -m 'mCBm-1 re-add d' $ hg log -G --rev '::(desc("mCBm")+desc("mBCm"))' @ 12 mCBm-1 re-add d] | o 11 mCBm-0 simple merge - the other way] |\ | | o 10 mBCm-1 re-add d] | | | +---o 9 mBCm-0 simple merge - one way] | |/ | o 8 c-1 delete d] | | o | 5 b-1: b update] |/ o 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h] Create a branch that delete a file previous renamed and recreate it $ hg up 'desc("i-2")' 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg rm d $ hg ci -m 'd-1 delete d' created new head $ echo bar > d $ hg add d $ hg ci -m 'd-2 re-add d' $ hg log -G --rev '::.' @ 14 d-2 re-add d] | o 13 d-1 delete d] | o 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h] Merge: - one with change to an unrelated file - one deleting and recreating the file Note: | In this case, the merge get conflicting information since on one side we have | a "brand new" d. and one the other one we have "d renamed from c (itself | renamed from c)". | | The current code arbitrarily pick one side $ hg up 'desc("b-1")' 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("d-2")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ hg ci -m 'mBDm-0 simple merge - one way' $ hg up 'desc("d-2")' 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("b-1")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ hg ci -m 'mDBm-0 simple merge - the other way' created new head $ hg log -G --rev '::(desc("mDBm")+desc("mBDm"))' @ 16 mDBm-0 simple merge - the other way] |\ +---o 15 mBDm-0 simple merge - one way] | |/ | o 14 d-2 re-add d] | | | o 13 d-1 delete d] | | o | 5 b-1: b update] |/ o 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h] Having another branch renaming a different file to the same filename as another $ hg up 'desc("i-2")' 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg mv b g $ hg ci -m 'e-1 b -move-> g' created new head $ hg mv g f $ hg ci -m 'e-2 g -move-> f' $ hg log -G --rev '::.' @ 18 e-2 g -move-> f] | o 17 e-1 b -move-> g] | o 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h] Merge: - the "e-" branch renaming b to f (through 'g') - the "a-" branch renaming d to f (through e) $ hg up 'desc("a-2")' 2 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg merge 'desc("e-2")' 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) $ hg ci -m 'mAEm-0 simple merge - one way' $ hg up 'desc("e-2")' 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("a-2")' 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) $ hg ci -m 'mEAm-0 simple merge - the other way' created new head $ hg log -G --rev '::(desc("mAEm")+desc("mEAm"))' @ 20 mEAm-0 simple merge - the other way] |\ +---o 19 mAEm-0 simple merge - one way] | |/ | o 18 e-2 g -move-> f] | | | o 17 e-1 b -move-> g] | | o | 4 a-2: e -move-> f] | | o | 3 a-1: d -move-> e] |/ o 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h] Note: | In this case, one of the merge wrongly record a merge while there is none. | This lead to bad copy tracing information to be dug up. Merge: - one with change to an unrelated file (b) - one overwriting a file (d) with a rename (from h to i to d) $ hg up 'desc("i-2")' 2 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg mv h i $ hg commit -m "f-1: rename h -> i" created new head $ hg mv --force i d $ hg commit -m "f-2: rename i -> d" $ hg debugindex d rev linkrev nodeid p1 p2 0 2 01c2f5eabdc4 000000000000 000000000000 1 10 b004912a8510 000000000000 000000000000 2 15 0bb5445dc4d0 01c2f5eabdc4 b004912a8510 3 22 c72365ee036f 000000000000 000000000000 $ hg up 'desc("b-1")' 3 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("f-2")' 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) $ hg ci -m 'mBFm-0 simple merge - one way' $ hg up 'desc("f-2")' 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("b-1")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ hg ci -m 'mFBm-0 simple merge - the other way' created new head $ hg log -G --rev '::(desc("mBFm")+desc("mFBm"))' @ 24 mFBm-0 simple merge - the other way] |\ +---o 23 mBFm-0 simple merge - one way] | |/ | o 22 f-2: rename i -> d] | | | o 21 f-1: rename h -> i] | | o | 5 b-1: b update] |/ o 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h] Merge: - one with change to a file - one deleting and recreating the file $ hg up 'desc("i-2")' 3 files updated, 0 files merged, 0 files removed, 0 files unresolved $ echo "some update" >> d $ hg commit -m "g-1: update d" created new head $ hg up 'desc("d-2")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("g-1")' --tool :union merging d 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ hg ci -m 'mDGm-0 simple merge - one way' $ hg up 'desc("g-1")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("d-2")' --tool :union merging d 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ hg ci -m 'mGDm-0 simple merge - the other way' created new head $ hg log -G --rev '::(desc("mDGm")+desc("mGDm"))' @ 27 mGDm-0 simple merge - the other way] |\ +---o 26 mDGm-0 simple merge - one way] | |/ | o 25 g-1: update d] | | o | 14 d-2 re-add d] | | o | 13 d-1 delete d] |/ o 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h] Check results ============= merging with unrelated change does not interfer wit the renames --------------------------------------------------------------- - rename on one side - unrelated change on the other side $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mABm")' A f d R d $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBAm")' A f d R d $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mABm")' M b $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mBAm")' M b $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mABm")' M b A f d R d $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBAm")' M b A f d R d $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mABm")' M b A f a R a $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBAm")' M b A f a R a merging with the side having a delete ------------------------------------- case summary: - one with change to an unrelated file - one deleting the change and recreate an unrelated file after the merge checks: - comparing from the merge $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBCm-0")' R d $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mCBm-0")' R d $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mBCm-0")' M b $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCBm-0")' M b $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBCm-0")' M b R d $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mCBm-0")' M b R d $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBCm-0")' M b R a $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCBm-0")' M b R a - comparing with the merge children re-adding the file $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBCm-1")' M d $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mCBm-1")' M d $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mBCm-1")' M b A d $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCBm-1")' M b A d $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBCm-1")' M b M d $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mCBm-1")' M b M d $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBCm-1")' M b A d R a $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCBm-1")' M b A d R a Comparing with a merge re-adding the file afterward --------------------------------------------------- Merge: - one with change to an unrelated file - one deleting and recreating the change Note: | In this case, one of the merge wrongly record a merge while there is none. | This lead to bad copy tracing information to be dug up. $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBDm-0")' M d $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mDBm-0")' M d $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mBDm-0")' M b M d $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mDBm-0")' M b $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBDm-0")' M b M d $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mDBm-0")' M b M d The bugs makes recorded copy is different depending of where we started the merge from since $ hg manifest --debug --rev 'desc("mBDm-0")' | grep '644 d' 0bb5445dc4d02f4e0d86cf16f9f3a411d0f17744 644 d $ hg manifest --debug --rev 'desc("mDBm-0")' | grep '644 d' b004912a8510032a0350a74daa2803dadfb00e12 644 d The 0bb5445dc4d02f4e0d86cf16f9f3a411d0f17744 entry is wrong, since the file was deleted on one side (then recreate) and untouched on the other side, no "merge" has happened. The resulting `d` file is the untouched version from branch `D`, not a merge. $ hg manifest --debug --rev 'desc("d-2")' | grep '644 d' b004912a8510032a0350a74daa2803dadfb00e12 644 d $ hg manifest --debug --rev 'desc("b-1")' | grep '644 d' 01c2f5eabdc4ce2bdee42b5f86311955e6c8f573 644 d $ hg debugindex d rev linkrev nodeid p1 p2 0 2 01c2f5eabdc4 000000000000 000000000000 1 10 b004912a8510 000000000000 000000000000 2 15 0bb5445dc4d0 01c2f5eabdc4 b004912a8510 3 22 c72365ee036f 000000000000 000000000000 4 23 863d9bc49190 01c2f5eabdc4 c72365ee036f 5 25 7bded9d9da1f 01c2f5eabdc4 000000000000 6 26 f04cac32d703 b004912a8510 7bded9d9da1f 7 27 d7a5eafb9322 7bded9d9da1f b004912a8510 (This `hg log` output if wrong, since no merge actually happened). $ hg log -Gfr 'desc("mBDm-0")' d o 15 mBDm-0 simple merge - one way] |\ o : 14 d-2 re-add d] :/ o 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h] This `hg log` output is correct $ hg log -Gfr 'desc("mDBm-0")' d o 14 d-2 re-add d] | ~ $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBDm-0")' M b A d a R a $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mDBm-0")' M b A d R a Comparing with a merge with colliding rename -------------------------------------------- - the "e-" branch renaming b to f (through 'g') - the "a-" branch renaming d to f (through e) $ hg manifest --debug --rev 'desc("mAEm-0")' | grep '644 f' eb806e34ef6be4c264effd5933d31004ad15a793 644 f $ hg manifest --debug --rev 'desc("mEAm-0")' | grep '644 f' eb806e34ef6be4c264effd5933d31004ad15a793 644 f $ hg manifest --debug --rev 'desc("a-2")' | grep '644 f' 0dd616bc7ab1a111921d95d76f69cda5c2ac539c 644 f $ hg manifest --debug --rev 'desc("e-2")' | grep '644 f' 6da5a2eecb9c833f830b67a4972366d49a9a142c 644 f $ hg debugindex f rev linkrev nodeid p1 p2 0 4 0dd616bc7ab1 000000000000 000000000000 1 18 6da5a2eecb9c 000000000000 000000000000 2 19 eb806e34ef6b 0dd616bc7ab1 6da5a2eecb9c $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mAEm-0")' M f R b $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mEAm-0")' M f R b $ hg status --copies --rev 'desc("e-2")' --rev 'desc("mAEm-0")' M f R d $ hg status --copies --rev 'desc("e-2")' --rev 'desc("mEAm-0")' M f R d $ hg status --copies --rev 'desc("i-2")' --rev 'desc("a-2")' A f d R d $ hg status --copies --rev 'desc("i-2")' --rev 'desc("e-2")' A f b R b $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mAEm-0")' A f d R b R d $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mEAm-0")' A f d R b R d $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAEm-0")' A f a R a R b $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEAm-0")' A f a R a R b Merge: - one with change to an unrelated file (b) - one overwriting a file (d) with a rename (from h to i to d) The overwriting should take over. However, the behavior is currently buggy $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBFm-0")' M b A d a (true !) h (false !) R a R h $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFBm-0")' M b A d h R a R h $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBFm-0")' M d R h $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mBFm-0")' M b M d $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mBFm-0")' M b M d R i $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mFBm-0")' M d R h $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mFBm-0")' M b $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mFBm-0")' M b M d R i The following graphlog is wrong, the "a -> c -> d" chain was overwritten and should not appear. $ hg log -Gfr 'desc("mBFm-0")' d o 23 mBFm-0 simple merge - one way] |\ o : 22 f-2: rename i -> d] | : o : 21 f-1: rename h -> i] :/ o 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h] The following output is correct. $ hg log -Gfr 'desc("mFBm-0")' d o 22 f-2: rename i -> d] | o 21 f-1: rename h -> i] : o 0 i-0 initial commit: a b h] Merge: - one with change to a file - one deleting and recreating the file Unlike in the 'BD/DB' cases, an actuall merge happened here. So we should consider history and rename on both branch of the merge. $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mDGm-0")' A d a R a $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGDm-0")' A d a R a $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mDGm-0")' M d $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mGDm-0")' M d $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mDGm-0")' M d $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mGDm-0")' M d $ hg log -Gfr 'desc("mDGm-0")' d o 26 mDGm-0 simple merge - one way] |\ | o 25 g-1: update d] | | o | 14 d-2 re-add d] |/ o 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h] $ hg log -Gfr 'desc("mDGm-0")' d o 26 mDGm-0 simple merge - one way] |\ | o 25 g-1: update d] | | o | 14 d-2 re-add d] |/ o 2 i-2: c -move-> d] | o 1 i-1: a -move-> c] | o 0 i-0 initial commit: a b h]