{"thread":{"id":"52895","subject":"[PATCH 0/5] Testcase cleanups (merge related)","startedAt":"2020-02-27T00:14:29Z","lastAt":"2020-03-13T18:11:37Z","messageCount":16,"participants":["Elijah Newren via GitGitGadget","SZEDER Gábor","Elijah Newren"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"392589","messageId":"pull.716.git.git.1582762465.gitgitgadget@gmail.com","threadId":"52895","inReplyTo":null,"subject":"[PATCH 0/5] Testcase cleanups (merge related)","fromName":"Elijah Newren via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-27T00:14:19Z","receivedAt":"2020-02-27T00:14:29Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"This series has a few testcase cleanups, and a new testcase. In more detail:\n\n * The first three patches are just various forms of testcase modernization\n * The fourth patch updates some tests to check intended behavior instead of\n   a proxy thereof\n * The fifth patch adds a new simple testcase that there is no other\n   merge/rebase/cherry-pick test for in our testsuite, just for added\n   defensiveness.\n\nAs a side note: t60[01]* is used by rev-list, and then t60[234].sh is kinda\ntaken by merge-recursive except that t6030 and t6041 are for bisect and\nt6040 for remote tracking stuff. Because t60[234].sh got filled up, rev-list\nspilled over to t61[01]* as well. It's all kind of a mess. I'm curious if\nmoving the merge stuff over to t64* would make sense, since that'd keep the\nmerge stuff together, and would also free up space for rev-list, bisect,\nremote-tracking and whatnot. Would that just be too much churn?\n\nElijah Newren (5):\n  t602[1236], t6034: modernize test formatting\n  t6020, t6022, t6035: update merge tests to use test helper functions\n  t3035: prefer test_must_fail to bash negation for git commands\n  t6022, t6046: test expected behavior instead of testing a proxy for it\n  t6020: new test with interleaved lexicographic ordering of directories\n\n t/t3035-merge-sparse.sh                |   4 +-\n t/t6020-merge-df.sh                    |  55 ++-\n t/t6021-merge-criss-cross.sh           | 135 +++---\n t/t6022-merge-rename.sh                | 382 +++++++++--------\n t/t6023-merge-file.sh                  | 568 +++++++++++++------------\n t/t6026-merge-attr.sh                  |  46 +-\n t/t6034-merge-rename-nocruft.sh        | 122 +++---\n t/t6035-merge-dir-to-symlink.sh        |  28 +-\n t/t6046-merge-skip-unneeded-updates.sh |  89 ++--\n 9 files changed, 752 insertions(+), 677 deletions(-)\n\n\nbase-commit: 2d2118b814c11f509e1aa76cb07110f7231668dc\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-716%2Fnewren%2Ftestcase-cleanups-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-716/newren/testcase-cleanups-v1\nPull-Request: https://github.com/git/git/pull/716\n-- \ngitgitgadget\n"},{"id":"392590","messageId":"9e02a22dd00895304051519abfa34ecbf80f9ea0.1582762465.git.gitgitgadget@gmail.com","threadId":"52895","inReplyTo":"pull.716.git.git.1582762465.gitgitgadget@gmail.com","subject":"[PATCH 3/5] t3035: prefer test_must_fail to bash negation for git commands","fromName":"Elijah Newren via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-27T00:14:22Z","receivedAt":"2020-02-27T00:14:31Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"From: Elijah Newren <newren@gmail.com>\n\nSigned-off-by: Elijah Newren <newren@gmail.com>\n---\n t/t3035-merge-sparse.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t3035-merge-sparse.sh b/t/t3035-merge-sparse.sh\nindex c4b4a94324a..74562e12356 100755\n--- a/t/t3035-merge-sparse.sh\n+++ b/t/t3035-merge-sparse.sh\n@@ -28,7 +28,7 @@ test_expect_success 'setup' '\n \tgit config core.sparseCheckout true &&\n \techo \"/checked-out\" >.git/info/sparse-checkout &&\n \tgit reset --hard &&\n-\t! git merge theirs\n+\ttest_must_fail git merge theirs\n '\n \n test_expect_success 'reset --hard works after the conflict' '\n@@ -42,7 +42,7 @@ test_expect_success 'is reset properly' '\n '\n \n test_expect_success 'setup: conflict back' '\n-\t! git merge theirs\n+\ttest_must_fail git merge theirs\n '\n \n test_expect_success 'Merge abort works after the conflict' '\n-- \ngitgitgadget\n\n"},{"id":"392591","messageId":"f0fd134c8d0c6a50415d6a74e1f7a508ee2e1209.1582762465.git.gitgitgadget@gmail.com","threadId":"52895","inReplyTo":"pull.716.git.git.1582762465.gitgitgadget@gmail.com","subject":"[PATCH 2/5] t6020, t6022, t6035: update merge tests to use test helper functions","fromName":"Elijah Newren via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-27T00:14:21Z","receivedAt":"2020-02-27T00:14:32Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"From: Elijah Newren <newren@gmail.com>\n\nMake use of test_path_is_file, test_write_lines, and similar helpers\nin these old test files.\n\nSigned-off-by: Elijah Newren <newren@gmail.com>\n---\n t/t6020-merge-df.sh             | 12 ++++----\n t/t6022-merge-rename.sh         | 54 ++++++++++++++++-----------------\n t/t6035-merge-dir-to-symlink.sh | 28 ++++++++---------\n 3 files changed, 47 insertions(+), 47 deletions(-)\n\ndiff --git a/t/t6020-merge-df.sh b/t/t6020-merge-df.sh\nindex 46b506b3b7b..cf662068da1 100755\n--- a/t/t6020-merge-df.sh\n+++ b/t/t6020-merge-df.sh\n@@ -83,9 +83,9 @@ test_expect_success 'modify/delete + directory/file conflict' '\n \ttest 4 -eq $(git ls-files -u | wc -l) &&\n \ttest 1 -eq $(git ls-files -o | wc -l) &&\n \n-\ttest -f letters/file &&\n-\ttest -f letters.txt &&\n-\ttest -f letters~modify\n+\ttest_path_is_file letters/file &&\n+\ttest_path_is_file letters.txt &&\n+\ttest_path_is_file letters~modify\n '\n \n test_expect_success 'modify/delete + directory/file conflict; other way' '\n@@ -99,9 +99,9 @@ test_expect_success 'modify/delete + directory/file conflict; other way' '\n \ttest 4 -eq $(git ls-files -u | wc -l) &&\n \ttest 1 -eq $(git ls-files -o | wc -l) &&\n \n-\ttest -f letters/file &&\n-\ttest -f letters.txt &&\n-\ttest -f letters~HEAD\n+\ttest_path_is_file letters/file &&\n+\ttest_path_is_file letters.txt &&\n+\ttest_path_is_file letters~HEAD\n '\n \n test_done\ndiff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh\nindex 1e34e1f48bb..6f196aaf276 100755\n--- a/t/t6022-merge-rename.sh\n+++ b/t/t6022-merge-rename.sh\n@@ -295,8 +295,8 @@ test_expect_success 'Rename+D/F conflict; renamed file merges + dir not in way'\n \tgit merge --strategy=recursive dir-not-in-way &&\n \n \tgit diff --quiet &&\n-\ttest -f dir &&\n-\tprintf \"1\\n2\\n3\\n4\\n5555\\n6\\n7\\n8\\n9\\n10\\n11\\n\" >expected &&\n+\ttest_path_is_file dir &&\n+\ttest_write_lines 1 2 3 4 5555 6 7 8 9 10 11 >expected &&\n \ttest_cmp expected dir\n '\n \n@@ -316,8 +316,8 @@ test_expect_success 'Rename+D/F conflict; renamed file merges but dir in way' '\n \ttest_must_fail git diff --quiet &&\n \ttest_must_fail git diff --cached --quiet &&\n \n-\ttest -f dir/file-in-the-way &&\n-\ttest -f dir~HEAD &&\n+\ttest_path_is_file dir/file-in-the-way &&\n+\ttest_path_is_file dir~HEAD &&\n \ttest_cmp expected dir~HEAD\n '\n \n@@ -338,8 +338,8 @@ test_expect_success 'Same as previous, but merged other way' '\n \ttest_must_fail git diff --quiet &&\n \ttest_must_fail git diff --cached --quiet &&\n \n-\ttest -f dir/file-in-the-way &&\n-\ttest -f dir~renamed-file-has-no-conflicts &&\n+\ttest_path_is_file dir/file-in-the-way &&\n+\ttest_path_is_file dir~renamed-file-has-no-conflicts &&\n \ttest_cmp expected dir~renamed-file-has-no-conflicts\n '\n \n@@ -355,7 +355,7 @@ test_expect_success 'Rename+D/F conflict; renamed file cannot merge, dir not in\n \ttest_must_fail git diff --quiet &&\n \ttest_must_fail git diff --cached --quiet &&\n \n-\ttest -f dir &&\n+\ttest_path_is_file dir &&\n \tcat >expected <<-\\EOF &&\n \t1\n \t2\n@@ -391,8 +391,8 @@ test_expect_success 'Rename+D/F conflict; renamed file cannot merge and dir in t\n \ttest_must_fail git diff --quiet &&\n \ttest_must_fail git diff --cached --quiet &&\n \n-\ttest -f dir/file-in-the-way &&\n-\ttest -f dir~HEAD &&\n+\ttest_path_is_file dir/file-in-the-way &&\n+\ttest_path_is_file dir~HEAD &&\n \ttest_cmp expected dir~HEAD\n '\n \n@@ -409,8 +409,8 @@ test_expect_success 'Same as previous, but merged other way' '\n \ttest_must_fail git diff --quiet &&\n \ttest_must_fail git diff --cached --quiet &&\n \n-\ttest -f dir/file-in-the-way &&\n-\ttest -f dir~renamed-file-has-conflicts &&\n+\ttest_path_is_file dir/file-in-the-way &&\n+\ttest_path_is_file dir~renamed-file-has-conflicts &&\n \tcat >expected <<-\\EOF &&\n \t1\n \t2\n@@ -463,9 +463,9 @@ test_expect_success 'both rename source and destination involved in D/F conflict\n \n \ttest_must_fail git diff --quiet &&\n \n-\ttest -f destdir/foo &&\n-\ttest -f one &&\n-\ttest -f destdir~HEAD &&\n+\ttest_path_is_file destdir/foo &&\n+\ttest_path_is_file one &&\n+\ttest_path_is_file destdir~HEAD &&\n \ttest \"stuff\" = \"$(cat destdir~HEAD)\"\n '\n \n@@ -506,9 +506,9 @@ test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked\n \n \ttest 4 -eq $(find . | grep -v .git | wc -l) &&\n \n-\ttest -d one &&\n-\ttest -f one~rename-two &&\n-\ttest -f two &&\n+\ttest_path_is_dir one &&\n+\ttest_path_is_file one~rename-two &&\n+\ttest_path_is_file two &&\n \ttest \"other\" = $(cat one~rename-two) &&\n \ttest \"stuff\" = $(cat two)\n '\n@@ -526,8 +526,8 @@ test_expect_success 'pair rename to parent of other (D/F conflicts) w/ clean sta\n \n \ttest 3 -eq $(find . | grep -v .git | wc -l) &&\n \n-\ttest -f one &&\n-\ttest -f two &&\n+\ttest_path_is_file one &&\n+\ttest_path_is_file two &&\n \ttest \"other\" = $(cat one) &&\n \ttest \"stuff\" = $(cat two)\n '\n@@ -567,11 +567,11 @@ test_expect_success 'check handling of differently renamed file with D/F conflic\n \ttest 1 -eq \"$(git ls-files -u original | wc -l)\" &&\n \ttest 2 -eq \"$(git ls-files -o | wc -l)\" &&\n \n-\ttest -f one/file &&\n-\ttest -f two/file &&\n-\ttest -f one~HEAD &&\n-\ttest -f two~second-rename &&\n-\t! test -f original\n+\ttest_path_is_file one/file &&\n+\ttest_path_is_file two/file &&\n+\ttest_path_is_file one~HEAD &&\n+\ttest_path_is_file two~second-rename &&\n+\ttest_path_is_missing original\n '\n \n test_expect_success 'setup rename one file to two; directories moving out of the way' '\n@@ -606,9 +606,9 @@ test_expect_success 'check handling of differently renamed file with D/F conflic\n \ttest 1 -eq \"$(git ls-files -u original | wc -l)\" &&\n \ttest 0 -eq \"$(git ls-files -o | wc -l)\" &&\n \n-\ttest -f one &&\n-\ttest -f two &&\n-\t! test -f original\n+\ttest_path_is_file one &&\n+\ttest_path_is_file two &&\n+\ttest_path_is_missing original\n '\n \n test_expect_success 'setup avoid unnecessary update, normal rename' '\ndiff --git a/t/t6035-merge-dir-to-symlink.sh b/t/t6035-merge-dir-to-symlink.sh\nindex 9324ea44162..2eddcc7664e 100755\n--- a/t/t6035-merge-dir-to-symlink.sh\n+++ b/t/t6035-merge-dir-to-symlink.sh\n@@ -31,19 +31,19 @@ test_expect_success 'a/b-2/c/d is kept when clobbering symlink b' '\n \tgit rm --cached a/b &&\n \tgit commit -m \"untracked symlink remains\" &&\n \tgit checkout -f start^0 &&\n-\ttest -f a/b-2/c/d\n+\ttest_path_is_file a/b-2/c/d\n '\n \n test_expect_success 'checkout should not have deleted a/b-2/c/d' '\n \tgit checkout HEAD^0 &&\n \tgit reset --hard master &&\n \t git checkout start^0 &&\n-\t test -f a/b-2/c/d\n+\t test_path_is_file a/b-2/c/d\n '\n \n test_expect_success 'setup for merge test' '\n \tgit reset --hard &&\n-\ttest -f a/b-2/c/d &&\n+\ttest_path_is_file a/b-2/c/d &&\n \techo x > a/x &&\n \tgit add a/x &&\n \tgit commit -m x &&\n@@ -54,7 +54,7 @@ test_expect_success 'Handle D/F conflict, do not lose a/b-2/c/d in merge (resolv\n \tgit reset --hard &&\n \tgit checkout baseline^0 &&\n \tgit merge -s resolve master &&\n-\ttest -f a/b-2/c/d\n+\ttest_path_is_file a/b-2/c/d\n '\n \n test_expect_success SYMLINKS 'a/b was resolved as symlink' '\n@@ -65,7 +65,7 @@ test_expect_success 'Handle D/F conflict, do not lose a/b-2/c/d in merge (recurs\n \tgit reset --hard &&\n \tgit checkout baseline^0 &&\n \tgit merge -s recursive master &&\n-\ttest -f a/b-2/c/d\n+\ttest_path_is_file a/b-2/c/d\n '\n \n test_expect_success SYMLINKS 'a/b was resolved as symlink' '\n@@ -76,7 +76,7 @@ test_expect_success 'Handle F/D conflict, do not lose a/b-2/c/d in merge (resolv\n \tgit reset --hard &&\n \tgit checkout master^0 &&\n \tgit merge -s resolve baseline^0 &&\n-\ttest -f a/b-2/c/d\n+\ttest_path_is_file a/b-2/c/d\n '\n \n test_expect_success SYMLINKS 'a/b was resolved as symlink' '\n@@ -87,7 +87,7 @@ test_expect_success 'Handle F/D conflict, do not lose a/b-2/c/d in merge (recurs\n \tgit reset --hard &&\n \tgit checkout master^0 &&\n \tgit merge -s recursive baseline^0 &&\n-\ttest -f a/b-2/c/d\n+\ttest_path_is_file a/b-2/c/d\n '\n \n test_expect_success SYMLINKS 'a/b was resolved as symlink' '\n@@ -99,8 +99,8 @@ test_expect_failure 'do not lose untracked in merge (resolve)' '\n \tgit checkout baseline^0 &&\n \t>a/b/c/e &&\n \ttest_must_fail git merge -s resolve master &&\n-\ttest -f a/b/c/e &&\n-\ttest -f a/b-2/c/d\n+\ttest_path_is_file a/b/c/e &&\n+\ttest_path_is_file a/b-2/c/d\n '\n \n test_expect_success 'do not lose untracked in merge (recursive)' '\n@@ -108,8 +108,8 @@ test_expect_success 'do not lose untracked in merge (recursive)' '\n \tgit checkout baseline^0 &&\n \t>a/b/c/e &&\n \ttest_must_fail git merge -s recursive master &&\n-\ttest -f a/b/c/e &&\n-\ttest -f a/b-2/c/d\n+\ttest_path_is_file a/b/c/e &&\n+\ttest_path_is_file a/b-2/c/d\n '\n \n test_expect_success 'do not lose modifications in merge (resolve)' '\n@@ -140,7 +140,7 @@ test_expect_success 'merge should not have D/F conflicts (resolve)' '\n \tgit reset --hard &&\n \tgit checkout baseline^0 &&\n \tgit merge -s resolve test2 &&\n-\ttest -f a/b/c/d\n+\ttest_path_is_file a/b/c/d\n '\n \n test_expect_success SYMLINKS 'a/b-2 was resolved as symlink' '\n@@ -151,7 +151,7 @@ test_expect_success 'merge should not have D/F conflicts (recursive)' '\n \tgit reset --hard &&\n \tgit checkout baseline^0 &&\n \tgit merge -s recursive test2 &&\n-\ttest -f a/b/c/d\n+\ttest_path_is_file a/b/c/d\n '\n \n test_expect_success SYMLINKS 'a/b-2 was resolved as symlink' '\n@@ -162,7 +162,7 @@ test_expect_success 'merge should not have F/D conflicts (recursive)' '\n \tgit reset --hard &&\n \tgit checkout -b foo test2 &&\n \tgit merge -s recursive baseline^0 &&\n-\ttest -f a/b/c/d\n+\ttest_path_is_file a/b/c/d\n '\n \n test_expect_success SYMLINKS 'a/b-2 was resolved as symlink' '\n-- \ngitgitgadget\n\n"},{"id":"392592","messageId":"911de63afa274b0791e4d4252934a5e9b0031f10.1582762465.git.gitgitgadget@gmail.com","threadId":"52895","inReplyTo":"pull.716.git.git.1582762465.gitgitgadget@gmail.com","subject":"[PATCH 5/5] t6020: new test with interleaved lexicographic ordering of directories","fromName":"Elijah Newren via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-27T00:14:24Z","receivedAt":"2020-02-27T00:14:34Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"From: Elijah Newren <newren@gmail.com>\n\nIf a repository has two files:\n    foo/bar/baz\n    foo/bar-2/baz\nthen a simple lexicographic ordering of files and directories shows\n    ...\n    foo/bar\n    foo/bar-2\n    foo/bar/baz\n    ...\nand the appearance of foo/bar-2 between foo/bar and foo/bar/baz can trip\nup some codepaths.  Add a test to catch such cases.\n\nt6020 might be a slight misfit since this testcase does not test any\nkind of file/directory conflict.  However, it is similar in spirit to\nsome tests (4-6) already in t6020 that check cases where a *file* sorted\nbetween a directory and the files underneath that directory.  This\ntestcase differs in that now there is a *directory* that sorts in the\nmiddle.\n\nAlthough merge-recursive currently has no problems with this simple\ntestcase, I discovered that it's very possible to accidentally mess it\nup.  Further, we have no other merge or cherry-pick or rebase testcases\nin the entire testsuite that cover such a case, so I felt like it would\nbe a worthwhile addition to the testsuite.\n\nSigned-off-by: Elijah Newren <newren@gmail.com>\n---\n t/t6020-merge-df.sh | 43 +++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 43 insertions(+)\n\ndiff --git a/t/t6020-merge-df.sh b/t/t6020-merge-df.sh\nindex cf662068da1..400a4cd1392 100755\n--- a/t/t6020-merge-df.sh\n+++ b/t/t6020-merge-df.sh\n@@ -104,4 +104,47 @@ test_expect_success 'modify/delete + directory/file conflict; other way' '\n \ttest_path_is_file letters~HEAD\n '\n \n+test_expect_success 'Simple merge in repo with interesting pathnames' '\n+\t# Simple lexicographic ordering of files and directories would be:\n+\t#     foo\n+\t#     foo/bar\n+\t#     foo/bar-2\n+\t#     foo/bar/baz\n+\t#     foo/bar-2/baz\n+\t# The fact that foo/bar-2 appears between foo/bar and foo/bar/baz\n+\t# can trip up some codepaths, and is the point of this test.\n+\ttest_create_repo name-ordering &&\n+\t(\n+\t\tcd name-ordering &&\n+\n+\t\tmkdir -p foo/bar &&\n+\t\tmkdir -p foo/bar-2 &&\n+\t\t>foo/bar/baz &&\n+\t\t>foo/bar-2/baz &&\n+\t\tgit add . &&\n+\t\tgit commit -m initial &&\n+\n+\t\tgit branch main &&\n+\t\tgit branch other &&\n+\n+\t\tgit checkout other &&\n+\t\techo other >foo/bar-2/baz &&\n+\t\tgit add -u &&\n+\t\tgit commit -m other &&\n+\n+\t\tgit checkout main &&\n+\t\techo main >foo/bar/baz &&\n+\t\tgit add -u &&\n+\t\tgit commit -m main &&\n+\n+\t\tgit merge other &&\n+\t\tgit ls-files -s >out &&\n+\t\ttest_line_count = 2 out &&\n+\t\tgit rev-parse :0:foo/bar/baz :0:foo/bar-2/baz >actual &&\n+\t\tgit rev-parse HEAD~1:foo/bar/baz other:foo/bar-2/baz >expect &&\n+\t\ttest_cmp expect actual\n+\t)\n+\n+'\n+\n test_done\n-- \ngitgitgadget\n"},{"id":"392593","messageId":"d5bb4b5756781e3759e4aa883ffc63802e0a5e17.1582762465.git.gitgitgadget@gmail.com","threadId":"52895","inReplyTo":"pull.716.git.git.1582762465.gitgitgadget@gmail.com","subject":"[PATCH 1/5] t602[1236], t6034: modernize test formatting","fromName":"Elijah Newren via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-27T00:14:20Z","receivedAt":"2020-02-27T00:14:34Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"From: Elijah Newren <newren@gmail.com>\n\nIndent code, and include it inside test_expect* blocks.\n\nSigned-off-by: Elijah Newren <newren@gmail.com>\n---\n t/t6021-merge-criss-cross.sh    | 135 +++-----\n t/t6022-merge-rename.sh         | 315 +++++++++---------\n t/t6023-merge-file.sh           | 568 +++++++++++++++++---------------\n t/t6026-merge-attr.sh           |  46 +--\n t/t6034-merge-rename-nocruft.sh | 122 ++++---\n 5 files changed, 591 insertions(+), 595 deletions(-)\n\ndiff --git a/t/t6021-merge-criss-cross.sh b/t/t6021-merge-criss-cross.sh\nindex d254e020b6d..9d5e992878f 100755\n--- a/t/t6021-merge-criss-cross.sh\n+++ b/t/t6021-merge-criss-cross.sh\n@@ -10,87 +10,58 @@\n test_description='Test criss-cross merge'\n . ./test-lib.sh\n \n-test_expect_success 'prepare repository' \\\n-'echo \"1\n-2\n-3\n-4\n-5\n-6\n-7\n-8\n-9\" > file &&\n-git add file &&\n-git commit -m \"Initial commit\" file &&\n-git branch A &&\n-git branch B &&\n-git checkout A &&\n-echo \"1\n-2\n-3\n-4\n-5\n-6\n-7\n-8 changed in B8, branch A\n-9\" > file &&\n-git commit -m \"B8\" file &&\n-git checkout B &&\n-echo \"1\n-2\n-3 changed in C3, branch B\n-4\n-5\n-6\n-7\n-8\n-9\n-\" > file &&\n-git commit -m \"C3\" file &&\n-git branch C3 &&\n-git merge -m \"pre E3 merge\" A &&\n-echo \"1\n-2\n-3 changed in E3, branch B. New file size\n-4\n-5\n-6\n-7\n-8 changed in B8, branch A\n-9\n-\" > file &&\n-git commit -m \"E3\" file &&\n-git checkout A &&\n-git merge -m \"pre D8 merge\" C3 &&\n-echo \"1\n-2\n-3 changed in C3, branch B\n-4\n-5\n-6\n-7\n-8 changed in D8, branch A. New file size 2\n-9\" > file &&\n-git commit -m D8 file'\n-\n-test_expect_success 'Criss-cross merge' 'git merge -m \"final merge\" B'\n-\n-cat > file-expect <<EOF\n-1\n-2\n-3 changed in E3, branch B. New file size\n-4\n-5\n-6\n-7\n-8 changed in D8, branch A. New file size 2\n-9\n-EOF\n-\n-test_expect_success 'Criss-cross merge result' 'cmp file file-expect'\n-\n-test_expect_success 'Criss-cross merge fails (-s resolve)' \\\n-'git reset --hard A^ &&\n-test_must_fail git merge -s resolve -m \"final merge\" B'\n+test_expect_success 'prepare repository' '\n+\ttest_write_lines 1 2 3 4 5 6 7 8 9 >file &&\n+\tgit add file &&\n+\tgit commit -m \"Initial commit\" file &&\n+\n+\tgit branch A &&\n+\tgit branch B &&\n+\tgit checkout A &&\n+\n+\ttest_write_lines 1 2 3 4 5 6 7 \"8 changed in B8, branch A\" 9 >file &&\n+\tgit commit -m \"B8\" file &&\n+\tgit checkout B &&\n+\n+\ttest_write_lines 1 2 \"3 changed in C3, branch B\" 4 5 6 7 8 9 >file &&\n+\tgit commit -m \"C3\" file &&\n+\tgit branch C3 &&\n+\n+\tgit merge -m \"pre E3 merge\" A &&\n+\n+\ttest_write_lines 1 2 \"3 changed in E3, branch B. New file size\" 4 5 6 7 \"8 changed in B8, branch A\" 9 >file &&\n+\tgit commit -m \"E3\" file &&\n+\n+\tgit checkout A &&\n+\tgit merge -m \"pre D8 merge\" C3 &&\n+\ttest_write_lines 1 2 \"3 changed in C3, branch B\" 4 5 6 7 \"8 changed in D8, branch A. New file size 2\" 9 >file &&\n+\n+\tgit commit -m D8 file\n+'\n+\n+test_expect_success 'Criss-cross merge' '\n+\tgit merge -m \"final merge\" B\n+'\n+\n+test_expect_success 'Criss-cross merge result' '\n+\tcat <<-\\EOF >file-expect &&\n+\t1\n+\t2\n+\t3 changed in E3, branch B. New file size\n+\t4\n+\t5\n+\t6\n+\t7\n+\t8 changed in D8, branch A. New file size 2\n+\t9\n+\tEOF\n+\n+\ttest_cmp file-expect file\n+'\n+\n+test_expect_success 'Criss-cross merge fails (-s resolve)' '\n+\tgit reset --hard A^ &&\n+\ttest_must_fail git merge -s resolve -m \"final merge\" B\n+'\n \n test_done\ndiff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh\nindex 53cc9b2ffbd..1e34e1f48bb 100755\n--- a/t/t6022-merge-rename.sh\n+++ b/t/t6022-merge-rename.sh\n@@ -8,94 +8,94 @@ modify () {\n \tmv \"$2.x\" \"$2\"\n }\n \n-test_expect_success setup \\\n-'\n-cat >A <<\\EOF &&\n-a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n-b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n-c cccccccccccccccccccccccccccccccccccccccccccccccc\n-d dddddddddddddddddddddddddddddddddddddddddddddddd\n-e eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n-f ffffffffffffffffffffffffffffffffffffffffffffffff\n-g gggggggggggggggggggggggggggggggggggggggggggggggg\n-h hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n-i iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\n-j jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj\n-k kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk\n-l llllllllllllllllllllllllllllllllllllllllllllllll\n-m mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm\n-n nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn\n-o oooooooooooooooooooooooooooooooooooooooooooooooo\n-EOF\n-\n-cat >M <<\\EOF &&\n-A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n-B BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n-C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n-D DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\n-E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n-F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n-G GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\n-H HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH\n-I IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\n-J JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ\n-K KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK\n-L LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL\n-M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n-N NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN\n-O OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\n-EOF\n-\n-git add A M &&\n-git commit -m \"initial has A and M\" &&\n-git branch white &&\n-git branch red &&\n-git branch blue &&\n-git branch yellow &&\n-git branch change &&\n-git branch change+rename &&\n-\n-sed -e \"/^g /s/.*/g : master changes a line/\" <A >A+ &&\n-mv A+ A &&\n-git commit -a -m \"master updates A\" &&\n-\n-git checkout yellow &&\n-rm -f M &&\n-git commit -a -m \"yellow removes M\" &&\n-\n-git checkout white &&\n-sed -e \"/^g /s/.*/g : white changes a line/\" <A >B &&\n-sed -e \"/^G /s/.*/G : colored branch changes a line/\" <M >N &&\n-rm -f A M &&\n-git update-index --add --remove A B M N &&\n-git commit -m \"white renames A->B, M->N\" &&\n-\n-git checkout red &&\n-sed -e \"/^g /s/.*/g : red changes a line/\" <A >B &&\n-sed -e \"/^G /s/.*/G : colored branch changes a line/\" <M >N &&\n-rm -f A M &&\n-git update-index --add --remove A B M N &&\n-git commit -m \"red renames A->B, M->N\" &&\n-\n-git checkout blue &&\n-sed -e \"/^g /s/.*/g : blue changes a line/\" <A >C &&\n-sed -e \"/^G /s/.*/G : colored branch changes a line/\" <M >N &&\n-rm -f A M &&\n-git update-index --add --remove A C M N &&\n-git commit -m \"blue renames A->C, M->N\" &&\n-\n-git checkout change &&\n-sed -e \"/^g /s/.*/g : changed line/\" <A >A+ &&\n-mv A+ A &&\n-git commit -q -a -m \"changed\" &&\n-\n-git checkout change+rename &&\n-sed -e \"/^g /s/.*/g : changed line/\" <A >B &&\n-rm A &&\n-git update-index --add B &&\n-git commit -q -a -m \"changed and renamed\" &&\n-\n-git checkout master'\n+test_expect_success 'setup' '\n+\tcat >A <<-\\EOF &&\n+\ta aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n+\tb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n+\tc cccccccccccccccccccccccccccccccccccccccccccccccc\n+\td dddddddddddddddddddddddddddddddddddddddddddddddd\n+\te eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n+\tf ffffffffffffffffffffffffffffffffffffffffffffffff\n+\tg gggggggggggggggggggggggggggggggggggggggggggggggg\n+\th hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n+\ti iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\n+\tj jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj\n+\tk kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk\n+\tl llllllllllllllllllllllllllllllllllllllllllllllll\n+\tm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm\n+\tn nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn\n+\to oooooooooooooooooooooooooooooooooooooooooooooooo\n+\tEOF\n+\n+\tcat >M <<-\\EOF &&\n+\tA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n+\tB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n+\tC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n+\tD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\n+\tE EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n+\tF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n+\tG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\n+\tH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH\n+\tI IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\n+\tJ JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ\n+\tK KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK\n+\tL LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL\n+\tM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n+\tN NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN\n+\tO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\n+\tEOF\n+\n+\tgit add A M &&\n+\tgit commit -m \"initial has A and M\" &&\n+\tgit branch white &&\n+\tgit branch red &&\n+\tgit branch blue &&\n+\tgit branch yellow &&\n+\tgit branch change &&\n+\tgit branch change+rename &&\n+\n+\tsed -e \"/^g /s/.*/g : master changes a line/\" <A >A+ &&\n+\tmv A+ A &&\n+\tgit commit -a -m \"master updates A\" &&\n+\n+\tgit checkout yellow &&\n+\trm -f M &&\n+\tgit commit -a -m \"yellow removes M\" &&\n+\n+\tgit checkout white &&\n+\tsed -e \"/^g /s/.*/g : white changes a line/\" <A >B &&\n+\tsed -e \"/^G /s/.*/G : colored branch changes a line/\" <M >N &&\n+\trm -f A M &&\n+\tgit update-index --add --remove A B M N &&\n+\tgit commit -m \"white renames A->B, M->N\" &&\n+\n+\tgit checkout red &&\n+\tsed -e \"/^g /s/.*/g : red changes a line/\" <A >B &&\n+\tsed -e \"/^G /s/.*/G : colored branch changes a line/\" <M >N &&\n+\trm -f A M &&\n+\tgit update-index --add --remove A B M N &&\n+\tgit commit -m \"red renames A->B, M->N\" &&\n+\n+\tgit checkout blue &&\n+\tsed -e \"/^g /s/.*/g : blue changes a line/\" <A >C &&\n+\tsed -e \"/^G /s/.*/G : colored branch changes a line/\" <M >N &&\n+\trm -f A M &&\n+\tgit update-index --add --remove A C M N &&\n+\tgit commit -m \"blue renames A->C, M->N\" &&\n+\n+\tgit checkout change &&\n+\tsed -e \"/^g /s/.*/g : changed line/\" <A >A+ &&\n+\tmv A+ A &&\n+\tgit commit -q -a -m \"changed\" &&\n+\n+\tgit checkout change+rename &&\n+\tsed -e \"/^g /s/.*/g : changed line/\" <A >B &&\n+\trm A &&\n+\tgit update-index --add B &&\n+\tgit commit -q -a -m \"changed and renamed\" &&\n+\n+\tgit checkout master\n+'\n \n test_expect_success 'pull renaming branch into unrenaming one' \\\n '\n@@ -288,14 +288,15 @@ test_expect_success 'setup for rename + d/f conflicts' '\n \tgit commit -m \"Conflicting change\"\n '\n \n-printf \"1\\n2\\n3\\n4\\n5555\\n6\\n7\\n8\\n9\\n10\\n11\\n\" >expected\n-\n test_expect_success 'Rename+D/F conflict; renamed file merges + dir not in way' '\n \tgit reset --hard &&\n \tgit checkout -q renamed-file-has-no-conflicts^0 &&\n+\n \tgit merge --strategy=recursive dir-not-in-way &&\n+\n \tgit diff --quiet &&\n \ttest -f dir &&\n+\tprintf \"1\\n2\\n3\\n4\\n5555\\n6\\n7\\n8\\n9\\n10\\n11\\n\" >expected &&\n \ttest_cmp expected dir\n '\n \n@@ -342,24 +343,6 @@ test_expect_success 'Same as previous, but merged other way' '\n \ttest_cmp expected dir~renamed-file-has-no-conflicts\n '\n \n-cat >expected <<\\EOF &&\n-1\n-2\n-3\n-4\n-5\n-6\n-7\n-8\n-9\n-10\n-<<<<<<< HEAD:dir\n-12\n-=======\n-11\n->>>>>>> dir-not-in-way:sub/file\n-EOF\n-\n test_expect_success 'Rename+D/F conflict; renamed file cannot merge, dir not in way' '\n \tgit reset --hard &&\n \trm -rf dir~* &&\n@@ -373,6 +356,23 @@ test_expect_success 'Rename+D/F conflict; renamed file cannot merge, dir not in\n \ttest_must_fail git diff --cached --quiet &&\n \n \ttest -f dir &&\n+\tcat >expected <<-\\EOF &&\n+\t1\n+\t2\n+\t3\n+\t4\n+\t5\n+\t6\n+\t7\n+\t8\n+\t9\n+\t10\n+\t<<<<<<< HEAD:dir\n+\t12\n+\t=======\n+\t11\n+\t>>>>>>> dir-not-in-way:sub/file\n+\tEOF\n \ttest_cmp expected dir\n '\n \n@@ -396,24 +396,6 @@ test_expect_success 'Rename+D/F conflict; renamed file cannot merge and dir in t\n \ttest_cmp expected dir~HEAD\n '\n \n-cat >expected <<\\EOF &&\n-1\n-2\n-3\n-4\n-5\n-6\n-7\n-8\n-9\n-10\n-<<<<<<< HEAD:sub/file\n-11\n-=======\n-12\n->>>>>>> renamed-file-has-conflicts:dir\n-EOF\n-\n test_expect_success 'Same as previous, but merged other way' '\n \tgit reset --hard &&\n \trm -rf dir~* &&\n@@ -429,6 +411,23 @@ test_expect_success 'Same as previous, but merged other way' '\n \n \ttest -f dir/file-in-the-way &&\n \ttest -f dir~renamed-file-has-conflicts &&\n+\tcat >expected <<-\\EOF &&\n+\t1\n+\t2\n+\t3\n+\t4\n+\t5\n+\t6\n+\t7\n+\t8\n+\t9\n+\t10\n+\t<<<<<<< HEAD:sub/file\n+\t11\n+\t=======\n+\t12\n+\t>>>>>>> renamed-file-has-conflicts:dir\n+\tEOF\n \ttest_cmp expected dir~renamed-file-has-conflicts\n '\n \n@@ -810,48 +809,48 @@ test_expect_success 'setup for use of extended merge markers' '\n \tgit commit -mC\n '\n \n-cat >expected <<\\EOF &&\n-1\n-2\n-3\n-4\n-5\n-6\n-7\n-8\n-<<<<<<< HEAD:renamed_file\n-9\n-=======\n-8.5\n->>>>>>> master^0:original_file\n-EOF\n-\n test_expect_success 'merge master into rename has correct extended markers' '\n \tgit checkout rename^0 &&\n \ttest_must_fail git merge -s recursive master^0 &&\n+\n+\tcat >expected <<-\\EOF &&\n+\t1\n+\t2\n+\t3\n+\t4\n+\t5\n+\t6\n+\t7\n+\t8\n+\t<<<<<<< HEAD:renamed_file\n+\t9\n+\t=======\n+\t8.5\n+\t>>>>>>> master^0:original_file\n+\tEOF\n \ttest_cmp expected renamed_file\n '\n \n-cat >expected <<\\EOF &&\n-1\n-2\n-3\n-4\n-5\n-6\n-7\n-8\n-<<<<<<< HEAD:original_file\n-8.5\n-=======\n-9\n->>>>>>> rename^0:renamed_file\n-EOF\n-\n test_expect_success 'merge rename into master has correct extended markers' '\n \tgit reset --hard &&\n \tgit checkout master^0 &&\n \ttest_must_fail git merge -s recursive rename^0 &&\n+\n+\tcat >expected <<-\\EOF &&\n+\t1\n+\t2\n+\t3\n+\t4\n+\t5\n+\t6\n+\t7\n+\t8\n+\t<<<<<<< HEAD:original_file\n+\t8.5\n+\t=======\n+\t9\n+\t>>>>>>> rename^0:renamed_file\n+\tEOF\n \ttest_cmp expected renamed_file\n '\n \ndiff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh\nindex 51ee887a776..2f421d967ab 100755\n--- a/t/t6023-merge-file.sh\n+++ b/t/t6023-merge-file.sh\n@@ -3,56 +3,59 @@\n test_description='RCS merge replacement: merge-file'\n . ./test-lib.sh\n \n-cat > orig.txt << EOF\n-Dominus regit me,\n-et nihil mihi deerit.\n-In loco pascuae ibi me collocavit,\n-super aquam refectionis educavit me;\n-animam meam convertit,\n-deduxit me super semitas jusitiae,\n-propter nomen suum.\n-EOF\n-\n-cat > new1.txt << EOF\n-Dominus regit me,\n-et nihil mihi deerit.\n-In loco pascuae ibi me collocavit,\n-super aquam refectionis educavit me;\n-animam meam convertit,\n-deduxit me super semitas jusitiae,\n-propter nomen suum.\n-Nam et si ambulavero in medio umbrae mortis,\n-non timebo mala, quoniam tu mecum es:\n-virga tua et baculus tuus ipsa me consolata sunt.\n-EOF\n-\n-cat > new2.txt << EOF\n-Dominus regit me, et nihil mihi deerit.\n-In loco pascuae ibi me collocavit,\n-super aquam refectionis educavit me;\n-animam meam convertit,\n-deduxit me super semitas jusitiae,\n-propter nomen suum.\n-EOF\n-\n-cat > new3.txt << EOF\n-DOMINUS regit me,\n-et nihil mihi deerit.\n-In loco pascuae ibi me collocavit,\n-super aquam refectionis educavit me;\n-animam meam convertit,\n-deduxit me super semitas jusitiae,\n-propter nomen suum.\n-EOF\n-\n-cat > new4.txt << EOF\n-Dominus regit me, et nihil mihi deerit.\n-In loco pascuae ibi me collocavit,\n-super aquam refectionis educavit me;\n-animam meam convertit,\n-deduxit me super semitas jusitiae,\n-EOF\n-printf \"propter nomen suum.\" >> new4.txt\n+test_expect_success 'setup' '\n+\tcat >orig.txt <<-\\EOF &&\n+\tDominus regit me,\n+\tet nihil mihi deerit.\n+\tIn loco pascuae ibi me collocavit,\n+\tsuper aquam refectionis educavit me;\n+\tanimam meam convertit,\n+\tdeduxit me super semitas jusitiae,\n+\tpropter nomen suum.\n+\tEOF\n+\n+\tcat >new1.txt <<-\\EOF &&\n+\tDominus regit me,\n+\tet nihil mihi deerit.\n+\tIn loco pascuae ibi me collocavit,\n+\tsuper aquam refectionis educavit me;\n+\tanimam meam convertit,\n+\tdeduxit me super semitas jusitiae,\n+\tpropter nomen suum.\n+\tNam et si ambulavero in medio umbrae mortis,\n+\tnon timebo mala, quoniam tu mecum es:\n+\tvirga tua et baculus tuus ipsa me consolata sunt.\n+\tEOF\n+\n+\tcat >new2.txt <<-\\EOF &&\n+\tDominus regit me, et nihil mihi deerit.\n+\tIn loco pascuae ibi me collocavit,\n+\tsuper aquam refectionis educavit me;\n+\tanimam meam convertit,\n+\tdeduxit me super semitas jusitiae,\n+\tpropter nomen suum.\n+\tEOF\n+\n+\tcat >new3.txt <<-\\EOF &&\n+\tDOMINUS regit me,\n+\tet nihil mihi deerit.\n+\tIn loco pascuae ibi me collocavit,\n+\tsuper aquam refectionis educavit me;\n+\tanimam meam convertit,\n+\tdeduxit me super semitas jusitiae,\n+\tpropter nomen suum.\n+\tEOF\n+\n+\tcat >new4.txt <<-\\EOF &&\n+\tDominus regit me, et nihil mihi deerit.\n+\tIn loco pascuae ibi me collocavit,\n+\tsuper aquam refectionis educavit me;\n+\tanimam meam convertit,\n+\tdeduxit me super semitas jusitiae,\n+\tEOF\n+\n+\tprintf \"propter nomen suum.\" >>new4.txt\n+'\n \n test_expect_success 'merge with no changes' '\n \tcp orig.txt test.txt &&\n@@ -60,9 +63,10 @@ test_expect_success 'merge with no changes' '\n \ttest_cmp test.txt orig.txt\n '\n \n-cp new1.txt test.txt\n-test_expect_success \"merge without conflict\" \\\n-\t\"git merge-file test.txt orig.txt new2.txt\"\n+test_expect_success \"merge without conflict\" '\n+\tcp new1.txt test.txt &&\n+\tgit merge-file test.txt orig.txt new2.txt\n+'\n \n test_expect_success 'works in subdirectory' '\n \tmkdir dir &&\n@@ -73,151 +77,176 @@ test_expect_success 'works in subdirectory' '\n \ttest_path_is_missing a.txt\n '\n \n-cp new1.txt test.txt\n-test_expect_success \"merge without conflict (--quiet)\" \\\n-\t\"git merge-file --quiet test.txt orig.txt new2.txt\"\n-\n-cp new1.txt test2.txt\n-test_expect_failure \"merge without conflict (missing LF at EOF)\" \\\n-\t\"git merge-file test2.txt orig.txt new4.txt\"\n-\n-test_expect_failure \"merge result added missing LF\" \\\n-\t\"test_cmp test.txt test2.txt\"\n-\n-cp new4.txt test3.txt\n-test_expect_success \"merge without conflict (missing LF at EOF, away from change in the other file)\" \\\n-\t\"git merge-file --quiet test3.txt new2.txt new3.txt\"\n-\n-cat > expect.txt << EOF\n-DOMINUS regit me,\n-et nihil mihi deerit.\n-In loco pascuae ibi me collocavit,\n-super aquam refectionis educavit me;\n-animam meam convertit,\n-deduxit me super semitas jusitiae,\n-EOF\n-printf \"propter nomen suum.\" >> expect.txt\n-\n-test_expect_success \"merge does not add LF away of change\" \\\n-\t\"test_cmp expect.txt test3.txt\"\n-\n-cp test.txt backup.txt\n-test_expect_success \"merge with conflicts\" \\\n-\t\"test_must_fail git merge-file test.txt orig.txt new3.txt\"\n-\n-cat > expect.txt << EOF\n-<<<<<<< test.txt\n-Dominus regit me, et nihil mihi deerit.\n-=======\n-DOMINUS regit me,\n-et nihil mihi deerit.\n->>>>>>> new3.txt\n-In loco pascuae ibi me collocavit,\n-super aquam refectionis educavit me;\n-animam meam convertit,\n-deduxit me super semitas jusitiae,\n-propter nomen suum.\n-Nam et si ambulavero in medio umbrae mortis,\n-non timebo mala, quoniam tu mecum es:\n-virga tua et baculus tuus ipsa me consolata sunt.\n-EOF\n-\n-test_expect_success \"expected conflict markers\" \"test_cmp expect.txt test.txt\"\n-\n-cp backup.txt test.txt\n-\n-cat > expect.txt << EOF\n-Dominus regit me, et nihil mihi deerit.\n-In loco pascuae ibi me collocavit,\n-super aquam refectionis educavit me;\n-animam meam convertit,\n-deduxit me super semitas jusitiae,\n-propter nomen suum.\n-Nam et si ambulavero in medio umbrae mortis,\n-non timebo mala, quoniam tu mecum es:\n-virga tua et baculus tuus ipsa me consolata sunt.\n-EOF\n-test_expect_success \"merge conflicting with --ours\" \\\n-\t\"git merge-file --ours test.txt orig.txt new3.txt && test_cmp expect.txt test.txt\"\n-cp backup.txt test.txt\n-\n-cat > expect.txt << EOF\n-DOMINUS regit me,\n-et nihil mihi deerit.\n-In loco pascuae ibi me collocavit,\n-super aquam refectionis educavit me;\n-animam meam convertit,\n-deduxit me super semitas jusitiae,\n-propter nomen suum.\n-Nam et si ambulavero in medio umbrae mortis,\n-non timebo mala, quoniam tu mecum es:\n-virga tua et baculus tuus ipsa me consolata sunt.\n-EOF\n-test_expect_success \"merge conflicting with --theirs\" \\\n-\t\"git merge-file --theirs test.txt orig.txt new3.txt && test_cmp expect.txt test.txt\"\n-cp backup.txt test.txt\n-\n-cat > expect.txt << EOF\n-Dominus regit me, et nihil mihi deerit.\n-DOMINUS regit me,\n-et nihil mihi deerit.\n-In loco pascuae ibi me collocavit,\n-super aquam refectionis educavit me;\n-animam meam convertit,\n-deduxit me super semitas jusitiae,\n-propter nomen suum.\n-Nam et si ambulavero in medio umbrae mortis,\n-non timebo mala, quoniam tu mecum es:\n-virga tua et baculus tuus ipsa me consolata sunt.\n-EOF\n-test_expect_success \"merge conflicting with --union\" \\\n-\t\"git merge-file --union test.txt orig.txt new3.txt && test_cmp expect.txt test.txt\"\n-cp backup.txt test.txt\n-\n-test_expect_success \"merge with conflicts, using -L\" \\\n-\t\"test_must_fail git merge-file -L 1 -L 2 test.txt orig.txt new3.txt\"\n-\n-cat > expect.txt << EOF\n-<<<<<<< 1\n-Dominus regit me, et nihil mihi deerit.\n-=======\n-DOMINUS regit me,\n-et nihil mihi deerit.\n->>>>>>> new3.txt\n-In loco pascuae ibi me collocavit,\n-super aquam refectionis educavit me;\n-animam meam convertit,\n-deduxit me super semitas jusitiae,\n-propter nomen suum.\n-Nam et si ambulavero in medio umbrae mortis,\n-non timebo mala, quoniam tu mecum es:\n-virga tua et baculus tuus ipsa me consolata sunt.\n-EOF\n-\n-test_expect_success \"expected conflict markers, with -L\" \\\n-\t\"test_cmp expect.txt test.txt\"\n-\n-sed \"s/ tu / TU /\" < new1.txt > new5.txt\n-test_expect_success \"conflict in removed tail\" \\\n-\t\"test_must_fail git merge-file -p orig.txt new1.txt new5.txt > out\"\n-\n-cat > expect << EOF\n-Dominus regit me,\n-et nihil mihi deerit.\n-In loco pascuae ibi me collocavit,\n-super aquam refectionis educavit me;\n-animam meam convertit,\n-deduxit me super semitas jusitiae,\n-propter nomen suum.\n-<<<<<<< orig.txt\n-=======\n-Nam et si ambulavero in medio umbrae mortis,\n-non timebo mala, quoniam TU mecum es:\n-virga tua et baculus tuus ipsa me consolata sunt.\n->>>>>>> new5.txt\n-EOF\n-\n-test_expect_success \"expected conflict markers\" \"test_cmp expect out\"\n+test_expect_success \"merge without conflict (--quiet)\" '\n+\tcp new1.txt test.txt &&\n+\tgit merge-file --quiet test.txt orig.txt new2.txt\n+'\n+\n+test_expect_failure \"merge without conflict (missing LF at EOF)\" '\n+\tcp new1.txt test2.txt &&\n+\tgit merge-file test2.txt orig.txt new4.txt\n+'\n+\n+test_expect_failure \"merge result added missing LF\" '\n+\ttest_cmp test.txt test2.txt\n+'\n+\n+test_expect_success \"merge without conflict (missing LF at EOF, away from change in the other file)\" '\n+\tcp new4.txt test3.txt &&\n+\tgit merge-file --quiet test3.txt new2.txt new3.txt\n+'\n+\n+test_expect_success \"merge does not add LF away of change\" '\n+\tcat >expect.txt <<-\\EOF &&\n+\tDOMINUS regit me,\n+\tet nihil mihi deerit.\n+\tIn loco pascuae ibi me collocavit,\n+\tsuper aquam refectionis educavit me;\n+\tanimam meam convertit,\n+\tdeduxit me super semitas jusitiae,\n+\tEOF\n+\tprintf \"propter nomen suum.\" >>expect.txt &&\n+\n+\ttest_cmp expect.txt test3.txt\n+'\n+\n+test_expect_success \"merge with conflicts\" '\n+\tcp test.txt backup.txt &&\n+\ttest_must_fail git merge-file test.txt orig.txt new3.txt\n+'\n+\n+test_expect_success \"expected conflict markers\" '\n+\tcat >expect.txt <<-\\EOF &&\n+\t<<<<<<< test.txt\n+\tDominus regit me, et nihil mihi deerit.\n+\t=======\n+\tDOMINUS regit me,\n+\tet nihil mihi deerit.\n+\t>>>>>>> new3.txt\n+\tIn loco pascuae ibi me collocavit,\n+\tsuper aquam refectionis educavit me;\n+\tanimam meam convertit,\n+\tdeduxit me super semitas jusitiae,\n+\tpropter nomen suum.\n+\tNam et si ambulavero in medio umbrae mortis,\n+\tnon timebo mala, quoniam tu mecum es:\n+\tvirga tua et baculus tuus ipsa me consolata sunt.\n+\tEOF\n+\n+\ttest_cmp expect.txt test.txt\n+'\n+\n+test_expect_success \"merge conflicting with --ours\" '\n+\tcp backup.txt test.txt &&\n+\n+\tcat >expect.txt <<-\\EOF &&\n+\tDominus regit me, et nihil mihi deerit.\n+\tIn loco pascuae ibi me collocavit,\n+\tsuper aquam refectionis educavit me;\n+\tanimam meam convertit,\n+\tdeduxit me super semitas jusitiae,\n+\tpropter nomen suum.\n+\tNam et si ambulavero in medio umbrae mortis,\n+\tnon timebo mala, quoniam tu mecum es:\n+\tvirga tua et baculus tuus ipsa me consolata sunt.\n+\tEOF\n+\n+\tgit merge-file --ours test.txt orig.txt new3.txt &&\n+\ttest_cmp expect.txt test.txt\n+'\n+\n+test_expect_success \"merge conflicting with --theirs\" '\n+\tcp backup.txt test.txt &&\n+\n+\tcat >expect.txt <<-\\EOF &&\n+\tDOMINUS regit me,\n+\tet nihil mihi deerit.\n+\tIn loco pascuae ibi me collocavit,\n+\tsuper aquam refectionis educavit me;\n+\tanimam meam convertit,\n+\tdeduxit me super semitas jusitiae,\n+\tpropter nomen suum.\n+\tNam et si ambulavero in medio umbrae mortis,\n+\tnon timebo mala, quoniam tu mecum es:\n+\tvirga tua et baculus tuus ipsa me consolata sunt.\n+\tEOF\n+\n+\tgit merge-file --theirs test.txt orig.txt new3.txt &&\n+\ttest_cmp expect.txt test.txt\n+'\n+\n+test_expect_success \"merge conflicting with --union\" '\n+\tcp backup.txt test.txt &&\n+\n+\tcat >expect.txt <<-\\EOF &&\n+\tDominus regit me, et nihil mihi deerit.\n+\tDOMINUS regit me,\n+\tet nihil mihi deerit.\n+\tIn loco pascuae ibi me collocavit,\n+\tsuper aquam refectionis educavit me;\n+\tanimam meam convertit,\n+\tdeduxit me super semitas jusitiae,\n+\tpropter nomen suum.\n+\tNam et si ambulavero in medio umbrae mortis,\n+\tnon timebo mala, quoniam tu mecum es:\n+\tvirga tua et baculus tuus ipsa me consolata sunt.\n+\tEOF\n+\n+\tgit merge-file --union test.txt orig.txt new3.txt &&\n+\ttest_cmp expect.txt test.txt\n+'\n+\n+test_expect_success \"merge with conflicts, using -L\" '\n+\tcp backup.txt test.txt &&\n+\n+\ttest_must_fail git merge-file -L 1 -L 2 test.txt orig.txt new3.txt\n+'\n+\n+test_expect_success \"expected conflict markers, with -L\" '\n+\tcat >expect.txt <<-\\EOF &&\n+\t<<<<<<< 1\n+\tDominus regit me, et nihil mihi deerit.\n+\t=======\n+\tDOMINUS regit me,\n+\tet nihil mihi deerit.\n+\t>>>>>>> new3.txt\n+\tIn loco pascuae ibi me collocavit,\n+\tsuper aquam refectionis educavit me;\n+\tanimam meam convertit,\n+\tdeduxit me super semitas jusitiae,\n+\tpropter nomen suum.\n+\tNam et si ambulavero in medio umbrae mortis,\n+\tnon timebo mala, quoniam tu mecum es:\n+\tvirga tua et baculus tuus ipsa me consolata sunt.\n+\tEOF\n+\n+\ttest_cmp expect.txt test.txt\n+'\n+\n+test_expect_success \"conflict in removed tail\" '\n+\tsed \"s/ tu / TU /\" <new1.txt >new5.txt &&\n+\ttest_must_fail git merge-file -p orig.txt new1.txt new5.txt >out\n+'\n+\n+test_expect_success \"expected conflict markers\" '\n+\tcat >expect <<-\\EOF &&\n+\tDominus regit me,\n+\tet nihil mihi deerit.\n+\tIn loco pascuae ibi me collocavit,\n+\tsuper aquam refectionis educavit me;\n+\tanimam meam convertit,\n+\tdeduxit me super semitas jusitiae,\n+\tpropter nomen suum.\n+\t<<<<<<< orig.txt\n+\t=======\n+\tNam et si ambulavero in medio umbrae mortis,\n+\tnon timebo mala, quoniam TU mecum es:\n+\tvirga tua et baculus tuus ipsa me consolata sunt.\n+\t>>>>>>> new5.txt\n+\tEOF\n+\n+\ttest_cmp expect out\n+'\n \n test_expect_success 'binary files cannot be merged' '\n \ttest_must_fail git merge-file -p \\\n@@ -225,59 +254,55 @@ test_expect_success 'binary files cannot be merged' '\n \tgrep \"Cannot merge binary files\" merge.err\n '\n \n-sed -e \"s/deerit.\\$/deerit;/\" -e \"s/me;\\$/me./\" < new5.txt > new6.txt\n-sed -e \"s/deerit.\\$/deerit,/\" -e \"s/me;\\$/me,/\" < new5.txt > new7.txt\n-\n test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' '\n+\tsed -e \"s/deerit.\\$/deerit;/\" -e \"s/me;\\$/me./\" <new5.txt >new6.txt &&\n+\tsed -e \"s/deerit.\\$/deerit,/\" -e \"s/me;\\$/me,/\" <new5.txt >new7.txt &&\n \n \ttest_must_fail git merge-file -p new6.txt new5.txt new7.txt > output &&\n-\ttest 1 = $(grep ======= < output | wc -l)\n-\n+\ttest 1 = $(grep ======= <output | wc -l)\n '\n \n-sed -e 's/deerit./&%%%%/' -e \"s/locavit,/locavit;/\"< new6.txt | tr '%' '\\012' > new8.txt\n-sed -e 's/deerit./&%%%%/' -e \"s/locavit,/locavit --/\" < new7.txt | tr '%' '\\012' > new9.txt\n-\n test_expect_success 'ZEALOUS_ALNUM' '\n+\tsed -e \"s/deerit./&%%%%/\" -e \"s/locavit,/locavit;/\" <new6.txt | tr % \"\\012\" >new8.txt &&\n+\tsed -e \"s/deerit./&%%%%/\" -e \"s/locavit,/locavit --/\" <new7.txt | tr % \"\\012\" >new9.txt &&\n \n \ttest_must_fail git merge-file -p \\\n-\t\tnew8.txt new5.txt new9.txt > merge.out &&\n-\ttest 1 = $(grep ======= < merge.out | wc -l)\n-\n+\t\tnew8.txt new5.txt new9.txt >merge.out &&\n+\ttest 1 = $(grep ======= <merge.out | wc -l)\n '\n \n-cat >expect <<\\EOF\n-Dominus regit me,\n-<<<<<<< new8.txt\n-et nihil mihi deerit;\n+test_expect_success '\"diff3 -m\" style output (1)' '\n+\tcat >expect <<-\\EOF &&\n+\tDominus regit me,\n+\t<<<<<<< new8.txt\n+\tet nihil mihi deerit;\n \n \n \n \n-In loco pascuae ibi me collocavit;\n-super aquam refectionis educavit me.\n-||||||| new5.txt\n-et nihil mihi deerit.\n-In loco pascuae ibi me collocavit,\n-super aquam refectionis educavit me;\n-=======\n-et nihil mihi deerit,\n+\tIn loco pascuae ibi me collocavit;\n+\tsuper aquam refectionis educavit me.\n+\t||||||| new5.txt\n+\tet nihil mihi deerit.\n+\tIn loco pascuae ibi me collocavit,\n+\tsuper aquam refectionis educavit me;\n+\t=======\n+\tet nihil mihi deerit,\n \n \n \n \n-In loco pascuae ibi me collocavit --\n-super aquam refectionis educavit me,\n->>>>>>> new9.txt\n-animam meam convertit,\n-deduxit me super semitas jusitiae,\n-propter nomen suum.\n-Nam et si ambulavero in medio umbrae mortis,\n-non timebo mala, quoniam TU mecum es:\n-virga tua et baculus tuus ipsa me consolata sunt.\n-EOF\n+\tIn loco pascuae ibi me collocavit --\n+\tsuper aquam refectionis educavit me,\n+\t>>>>>>> new9.txt\n+\tanimam meam convertit,\n+\tdeduxit me super semitas jusitiae,\n+\tpropter nomen suum.\n+\tNam et si ambulavero in medio umbrae mortis,\n+\tnon timebo mala, quoniam TU mecum es:\n+\tvirga tua et baculus tuus ipsa me consolata sunt.\n+\tEOF\n \n-test_expect_success '\"diff3 -m\" style output (1)' '\n \ttest_must_fail git merge-file -p --diff3 \\\n \t\tnew8.txt new5.txt new9.txt >actual &&\n \ttest_cmp expect actual\n@@ -290,61 +315,64 @@ test_expect_success '\"diff3 -m\" style output (2)' '\n \ttest_cmp expect actual\n '\n \n-cat >expect <<\\EOF\n-Dominus regit me,\n-<<<<<<<<<< new8.txt\n-et nihil mihi deerit;\n+test_expect_success 'marker size' '\n+\tcat >expect <<-\\EOF &&\n+\tDominus regit me,\n+\t<<<<<<<<<< new8.txt\n+\tet nihil mihi deerit;\n \n \n \n \n-In loco pascuae ibi me collocavit;\n-super aquam refectionis educavit me.\n-|||||||||| new5.txt\n-et nihil mihi deerit.\n-In loco pascuae ibi me collocavit,\n-super aquam refectionis educavit me;\n-==========\n-et nihil mihi deerit,\n+\tIn loco pascuae ibi me collocavit;\n+\tsuper aquam refectionis educavit me.\n+\t|||||||||| new5.txt\n+\tet nihil mihi deerit.\n+\tIn loco pascuae ibi me collocavit,\n+\tsuper aquam refectionis educavit me;\n+\t==========\n+\tet nihil mihi deerit,\n \n \n \n \n-In loco pascuae ibi me collocavit --\n-super aquam refectionis educavit me,\n->>>>>>>>>> new9.txt\n-animam meam convertit,\n-deduxit me super semitas jusitiae,\n-propter nomen suum.\n-Nam et si ambulavero in medio umbrae mortis,\n-non timebo mala, quoniam TU mecum es:\n-virga tua et baculus tuus ipsa me consolata sunt.\n-EOF\n+\tIn loco pascuae ibi me collocavit --\n+\tsuper aquam refectionis educavit me,\n+\t>>>>>>>>>> new9.txt\n+\tanimam meam convertit,\n+\tdeduxit me super semitas jusitiae,\n+\tpropter nomen suum.\n+\tNam et si ambulavero in medio umbrae mortis,\n+\tnon timebo mala, quoniam TU mecum es:\n+\tvirga tua et baculus tuus ipsa me consolata sunt.\n+\tEOF\n \n-test_expect_success 'marker size' '\n \ttest_must_fail git merge-file -p --marker-size=10 \\\n \t\tnew8.txt new5.txt new9.txt >actual &&\n \ttest_cmp expect actual\n '\n \n-printf \"line1\\nline2\\nline3\" >nolf-orig.txt\n-printf \"line1\\nline2\\nline3x\" >nolf-diff1.txt\n-printf \"line1\\nline2\\nline3y\" >nolf-diff2.txt\n+test_expect_success 'conflict at EOF without LF resolved by --ours' '\n+\tprintf \"line1\\nline2\\nline3\" >nolf-orig.txt &&\n+\tprintf \"line1\\nline2\\nline3x\" >nolf-diff1.txt &&\n+\tprintf \"line1\\nline2\\nline3y\" >nolf-diff2.txt &&\n \n-test_expect_success 'conflict at EOF without LF resolved by --ours' \\\n-\t'git merge-file -p --ours nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&\n-\t printf \"line1\\nline2\\nline3x\" >expect.txt &&\n-\t test_cmp expect.txt output.txt'\n+\tgit merge-file -p --ours nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&\n+\tprintf \"line1\\nline2\\nline3x\" >expect.txt &&\n+\ttest_cmp expect.txt output.txt\n+'\n \n-test_expect_success 'conflict at EOF without LF resolved by --theirs' \\\n-\t'git merge-file -p --theirs nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&\n-\t printf \"line1\\nline2\\nline3y\" >expect.txt &&\n-\t test_cmp expect.txt output.txt'\n+test_expect_success 'conflict at EOF without LF resolved by --theirs' '\n+\tgit merge-file -p --theirs nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&\n+\tprintf \"line1\\nline2\\nline3y\" >expect.txt &&\n+\ttest_cmp expect.txt output.txt\n+'\n \n-test_expect_success 'conflict at EOF without LF resolved by --union' \\\n-\t'git merge-file -p --union nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&\n-\t printf \"line1\\nline2\\nline3x\\nline3y\" >expect.txt &&\n-\t test_cmp expect.txt output.txt'\n+test_expect_success 'conflict at EOF without LF resolved by --union' '\n+\tgit merge-file -p --union nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&\n+\tprintf \"line1\\nline2\\nline3x\\nline3y\" >expect.txt &&\n+\ttest_cmp expect.txt output.txt\n+'\n \n test_expect_success 'conflict sections match existing line endings' '\n \tprintf \"1\\\\r\\\\n2\\\\r\\\\n3\" >crlf-orig.txt &&\ndiff --git a/t/t6026-merge-attr.sh b/t/t6026-merge-attr.sh\nindex 8f9b48a4937..5900358ce9c 100755\n--- a/t/t6026-merge-attr.sh\n+++ b/t/t6026-merge-attr.sh\n@@ -32,7 +32,29 @@ test_expect_success setup '\n \ttest_tick &&\n \tgit commit -m Side &&\n \n-\tgit tag anchor\n+\tgit tag anchor &&\n+\n+\tcat >./custom-merge <<-\\EOF &&\n+\t#!/bin/sh\n+\n+\torig=\"$1\" ours=\"$2\" theirs=\"$3\" exit=\"$4\" path=$5\n+\t(\n+\t\techo \"orig is $orig\"\n+\t\techo \"ours is $ours\"\n+\t\techo \"theirs is $theirs\"\n+\t\techo \"path is $path\"\n+\t\techo \"=== orig ===\"\n+\t\tcat \"$orig\"\n+\t\techo \"=== ours ===\"\n+\t\tcat \"$ours\"\n+\t\techo \"=== theirs ===\"\n+\t\tcat \"$theirs\"\n+\t) >\"$ours+\"\n+\tcat \"$ours+\" >\"$ours\"\n+\trm -f \"$ours+\"\n+\texit \"$exit\"\n+\tEOF\n+\tchmod +x ./custom-merge\n '\n \n test_expect_success merge '\n@@ -82,28 +104,6 @@ test_expect_success 'retry the merge with longer context' '\n \tgrep \"<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\" actual\n '\n \n-cat >./custom-merge <<\\EOF\n-#!/bin/sh\n-\n-orig=\"$1\" ours=\"$2\" theirs=\"$3\" exit=\"$4\" path=$5\n-(\n-\techo \"orig is $orig\"\n-\techo \"ours is $ours\"\n-\techo \"theirs is $theirs\"\n-\techo \"path is $path\"\n-\techo \"=== orig ===\"\n-\tcat \"$orig\"\n-\techo \"=== ours ===\"\n-\tcat \"$ours\"\n-\techo \"=== theirs ===\"\n-\tcat \"$theirs\"\n-) >\"$ours+\"\n-cat \"$ours+\" >\"$ours\"\n-rm -f \"$ours+\"\n-exit \"$exit\"\n-EOF\n-chmod +x ./custom-merge\n-\n test_expect_success 'custom merge backend' '\n \n \techo \"* merge=union\" >.gitattributes &&\ndiff --git a/t/t6034-merge-rename-nocruft.sh b/t/t6034-merge-rename-nocruft.sh\nindex 89871aa5b04..a25e7304604 100755\n--- a/t/t6034-merge-rename-nocruft.sh\n+++ b/t/t6034-merge-rename-nocruft.sh\n@@ -3,74 +3,73 @@\n test_description='Merge-recursive merging renames'\n . ./test-lib.sh\n \n-test_expect_success setup \\\n-'\n-cat >A <<\\EOF &&\n-a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n-b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n-c cccccccccccccccccccccccccccccccccccccccccccccccc\n-d dddddddddddddddddddddddddddddddddddddddddddddddd\n-e eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n-f ffffffffffffffffffffffffffffffffffffffffffffffff\n-g gggggggggggggggggggggggggggggggggggggggggggggggg\n-h hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n-i iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\n-j jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj\n-k kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk\n-l llllllllllllllllllllllllllllllllllllllllllllllll\n-m mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm\n-n nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn\n-o oooooooooooooooooooooooooooooooooooooooooooooooo\n-EOF\n+test_expect_success 'setup' '\n+\tcat >A <<-\\EOF &&\n+\ta aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n+\tb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n+\tc cccccccccccccccccccccccccccccccccccccccccccccccc\n+\td dddddddddddddddddddddddddddddddddddddddddddddddd\n+\te eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n+\tf ffffffffffffffffffffffffffffffffffffffffffffffff\n+\tg gggggggggggggggggggggggggggggggggggggggggggggggg\n+\th hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n+\ti iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\n+\tj jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj\n+\tk kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk\n+\tl llllllllllllllllllllllllllllllllllllllllllllllll\n+\tm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm\n+\tn nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn\n+\to oooooooooooooooooooooooooooooooooooooooooooooooo\n+\tEOF\n \n-cat >M <<\\EOF &&\n-A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n-B BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n-C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n-D DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\n-E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n-F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n-G GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\n-H HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH\n-I IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\n-J JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ\n-K KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK\n-L LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL\n-M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n-N NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN\n-O OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\n-EOF\n+\tcat >M <<-\\EOF &&\n+\tA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n+\tB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n+\tC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n+\tD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\n+\tE EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n+\tF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n+\tG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\n+\tH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH\n+\tI IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\n+\tJ JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ\n+\tK KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK\n+\tL LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL\n+\tM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n+\tN NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN\n+\tO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\n+\tEOF\n \n-git add A M &&\n-git commit -m \"initial has A and M\" &&\n-git branch white &&\n-git branch red &&\n-git branch blue &&\n+\tgit add A M &&\n+\tgit commit -m \"initial has A and M\" &&\n+\tgit branch white &&\n+\tgit branch red &&\n+\tgit branch blue &&\n \n-git checkout white &&\n-sed -e \"/^g /s/.*/g : white changes a line/\" <A >B &&\n-sed -e \"/^G /s/.*/G : colored branch changes a line/\" <M >N &&\n-rm -f A M &&\n-git update-index --add --remove A B M N &&\n-git commit -m \"white renames A->B, M->N\" &&\n+\tgit checkout white &&\n+\tsed -e \"/^g /s/.*/g : white changes a line/\" <A >B &&\n+\tsed -e \"/^G /s/.*/G : colored branch changes a line/\" <M >N &&\n+\trm -f A M &&\n+\tgit update-index --add --remove A B M N &&\n+\tgit commit -m \"white renames A->B, M->N\" &&\n \n-git checkout red &&\n-echo created by red >R &&\n-git update-index --add R &&\n-git commit -m \"red creates R\" &&\n+\tgit checkout red &&\n+\techo created by red >R &&\n+\tgit update-index --add R &&\n+\tgit commit -m \"red creates R\" &&\n \n-git checkout blue &&\n-sed -e \"/^o /s/.*/g : blue changes a line/\" <A >B &&\n-rm -f A &&\n-mv B A &&\n-git update-index A &&\n-git commit -m \"blue modify A\" &&\n+\tgit checkout blue &&\n+\tsed -e \"/^o /s/.*/g : blue changes a line/\" <A >B &&\n+\trm -f A &&\n+\tmv B A &&\n+\tgit update-index A &&\n+\tgit commit -m \"blue modify A\" &&\n \n-git checkout master'\n+\tgit checkout master\n+'\n \n # This test broke in 65ac6e9c3f47807cb603af07a6a9e1a43bc119ae\n-test_expect_success 'merge white into red (A->B,M->N)' \\\n-'\n+test_expect_success 'merge white into red (A->B,M->N)' '\n \tgit checkout -b red-white red &&\n \tgit merge white &&\n \tgit write-tree &&\n@@ -82,8 +81,7 @@ test_expect_success 'merge white into red (A->B,M->N)' \\\n '\n \n # This test broke in 8371234ecaaf6e14fe3f2082a855eff1bbd79ae9\n-test_expect_success 'merge blue into white (A->B, mod A, A untracked)' \\\n-'\n+test_expect_success 'merge blue into white (A->B, mod A, A untracked)' '\n \tgit checkout -b white-blue white &&\n \techo dirty >A &&\n \tgit merge blue &&\n-- \ngitgitgadget\n\n"},{"id":"392594","messageId":"26d0c34cd1d4a54dab28d0c9c2242336244e8a3c.1582762465.git.gitgitgadget@gmail.com","threadId":"52895","inReplyTo":"pull.716.git.git.1582762465.gitgitgadget@gmail.com","subject":"[PATCH 4/5] t6022, t6046: test expected behavior instead of testing a proxy for it","fromName":"Elijah Newren via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-27T00:14:23Z","receivedAt":"2020-02-27T00:14:35Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"From: Elijah Newren <newren@gmail.com>\n\nIn t6022, we were testing for file being overwritten (or not) based on\nan output message instead of checking for the file being overwritten.\nSince we can check for the file being overwritten via mtime updates,\ncheck that instead.\n\nIn t6046, we were largely checking for both the expected behavior and a\nproxy for it, which is unnecessary.  The calls to test-tool also were a\nbit cryptic.  Make them a little clearer.\n\nSigned-off-by: Elijah Newren <newren@gmail.com>\n---\n t/t6022-merge-rename.sh                | 15 ++++-\n t/t6046-merge-skip-unneeded-updates.sh | 89 +++++++++++++++++---------\n 2 files changed, 70 insertions(+), 34 deletions(-)\n\ndiff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh\nindex 6f196aaf276..d97cf48495b 100755\n--- a/t/t6022-merge-rename.sh\n+++ b/t/t6022-merge-rename.sh\n@@ -242,12 +242,23 @@ test_expect_success 'merge of identical changes in a renamed file' '\n \trm -f A M N &&\n \tgit reset --hard &&\n \tgit checkout change+rename &&\n+\n+\ttest-tool chmtime =31337 B &&\n+\ttest-tool chmtime --get B >old-mtime &&\n \tGIT_MERGE_VERBOSITY=3 git merge change >out &&\n-\ttest_i18ngrep \"^Skipped B\" out &&\n+\n+\ttest-tool chmtime --get B >new-mtime &&\n+\ttest_cmp old-mtime new-mtime &&\n+\n \tgit reset --hard HEAD^ &&\n \tgit checkout change &&\n+\n+\ttest-tool chmtime =-1 M &&\n+\ttest-tool chmtime --get M >old-mtime &&\n \tGIT_MERGE_VERBOSITY=3 git merge change+rename >out &&\n-\ttest_i18ngrep ! \"^Skipped B\" out\n+\n+\ttest-tool chmtime --get B >new-mtime &&\n+\ttest $(cat old-mtime) -lt $(cat new-mtime)\n '\n \n test_expect_success 'setup for rename + d/f conflicts' '\ndiff --git a/t/t6046-merge-skip-unneeded-updates.sh b/t/t6046-merge-skip-unneeded-updates.sh\nindex b7e46698321..962030ecdb6 100755\n--- a/t/t6046-merge-skip-unneeded-updates.sh\n+++ b/t/t6046-merge-skip-unneeded-updates.sh\n@@ -71,16 +71,16 @@ test_expect_success '1a-L: Modify(A)/Modify(B), change on B subset of A' '\n \n \t\tgit checkout A^0 &&\n \n-\t\ttest-tool chmtime =31337 b &&\n-\t\ttest-tool chmtime -v +0 b >expected-mtime &&\n+\t\ttest-tool chmtime =-1 b &&\n+\t\ttest-tool chmtime --get b >old-mtime &&\n \n \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&\n \n-\t\ttest_i18ngrep \"Skipped b\" out &&\n \t\ttest_must_be_empty err &&\n \n-\t\ttest-tool chmtime -v +0 b >actual-mtime &&\n-\t\ttest_cmp expected-mtime actual-mtime &&\n+\t\t# Make sure b was NOT updated\n+\t\ttest-tool chmtime --get b >new-mtime &&\n+\t\ttest_cmp old-mtime new-mtime &&\n \n \t\tgit ls-files -s >index_files &&\n \t\ttest_line_count = 1 index_files &&\n@@ -102,9 +102,14 @@ test_expect_success '1a-R: Modify(A)/Modify(B), change on B subset of A' '\n \n \t\tgit checkout B^0 &&\n \n+\t\ttest-tool chmtime =-1 b &&\n+\t\ttest-tool chmtime --get b >old-mtime &&\n \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&\n \n-\t\ttest_i18ngrep \"Auto-merging b\" out &&\n+\t\t# Make sure b WAS updated\n+\t\ttest-tool chmtime --get b >new-mtime &&\n+\t\ttest $(cat old-mtime) -lt $(cat new-mtime) &&\n+\n \t\ttest_must_be_empty err &&\n \n \t\tgit ls-files -s >index_files &&\n@@ -165,10 +170,10 @@ test_expect_success '2a-L: Modify/rename, merge into modify side' '\n \n \t\tgit checkout A^0 &&\n \n+\t\ttest_path_is_missing c &&\n \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&\n \n-\t\ttest_i18ngrep ! \"Skipped c\" out &&\n-\t\ttest_must_be_empty err &&\n+\t\ttest_path_is_file c &&\n \n \t\tgit ls-files -s >index_files &&\n \t\ttest_line_count = 1 index_files &&\n@@ -193,9 +198,14 @@ test_expect_success '2a-R: Modify/rename, merge into rename side' '\n \n \t\tgit checkout B^0 &&\n \n+\t\ttest-tool chmtime =-1 c &&\n+\t\ttest-tool chmtime --get c >old-mtime &&\n \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&\n \n-\t\ttest_i18ngrep ! \"Skipped c\" out &&\n+\t\t# Make sure c WAS updated\n+\t\ttest-tool chmtime --get c >new-mtime &&\n+\t\ttest $(cat old-mtime) -lt $(cat new-mtime) &&\n+\n \t\ttest_must_be_empty err &&\n \n \t\tgit ls-files -s >index_files &&\n@@ -256,16 +266,15 @@ test_expect_success '2b-L: Rename+Mod(A)/Mod(B), B mods subset of A' '\n \n \t\tgit checkout A^0 &&\n \n-\t\ttest-tool chmtime =31337 c &&\n-\t\ttest-tool chmtime -v +0 c >expected-mtime &&\n-\n+\t\ttest-tool chmtime =-1 c &&\n+\t\ttest-tool chmtime --get c >old-mtime &&\n \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&\n \n-\t\ttest_i18ngrep \"Skipped c\" out &&\n \t\ttest_must_be_empty err &&\n \n-\t\ttest-tool chmtime -v +0 c >actual-mtime &&\n-\t\ttest_cmp expected-mtime actual-mtime &&\n+\t\t# Make sure c WAS updated\n+\t\ttest-tool chmtime --get c >new-mtime &&\n+\t\ttest_cmp old-mtime new-mtime &&\n \n \t\tgit ls-files -s >index_files &&\n \t\ttest_line_count = 1 index_files &&\n@@ -290,9 +299,12 @@ test_expect_success '2b-R: Rename+Mod(A)/Mod(B), B mods subset of A' '\n \n \t\tgit checkout B^0 &&\n \n+\t\ttest_path_is_missing c &&\n \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&\n \n-\t\ttest_i18ngrep \"Auto-merging c\" out &&\n+\t\t# Make sure c now present (and thus was updated)\n+\t\ttest_path_is_file c &&\n+\n \t\ttest_must_be_empty err &&\n \n \t\tgit ls-files -s >index_files &&\n@@ -361,13 +373,18 @@ test_expect_success '2c: Modify b & add c VS rename b->c' '\n \n \t\tgit checkout A^0 &&\n \n+\t\ttest-tool chmtime =-1 c &&\n+\t\ttest-tool chmtime --get c >old-mtime &&\n \t\tGIT_MERGE_VERBOSITY=3 &&\n \t\texport GIT_MERGE_VERBOSITY &&\n \t\ttest_must_fail git merge -s recursive B^0 >out 2>err &&\n \n \t\ttest_i18ngrep \"CONFLICT (rename/add): Rename b->c\" out &&\n-\t\ttest_i18ngrep ! \"Skipped c\" out &&\n-\t\ttest_must_be_empty err\n+\t\ttest_must_be_empty err &&\n+\n+\t\t# Make sure c WAS updated\n+\t\ttest-tool chmtime --get c >new-mtime &&\n+\t\ttest $(cat old-mtime) -lt $(cat new-mtime)\n \n \t\t# FIXME: rename/add conflicts are horribly broken right now;\n \t\t# when I get back to my patch series fixing it and\n@@ -460,11 +477,13 @@ test_expect_success '3a-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' '\n \n \t\tgit checkout A^0 &&\n \n+\t\ttest_path_is_missing bar/bq &&\n \t\tGIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&\n \n-\t\ttest_i18ngrep ! \"Skipped bar/bq\" out &&\n \t\ttest_must_be_empty err &&\n \n+\t\ttest_path_is_file bar/bq &&\n+\n \t\tgit ls-files -s >index_files &&\n \t\ttest_line_count = 2 index_files &&\n \n@@ -488,11 +507,13 @@ test_expect_success '3a-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' '\n \n \t\tgit checkout B^0 &&\n \n+\t\ttest_path_is_missing bar/bq &&\n \t\tGIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err &&\n \n-\t\ttest_i18ngrep ! \"Skipped bar/bq\" out &&\n \t\ttest_must_be_empty err &&\n \n+\t\ttest_path_is_file bar/bq &&\n+\n \t\tgit ls-files -s >index_files &&\n \t\ttest_line_count = 2 index_files &&\n \n@@ -552,11 +573,13 @@ test_expect_success '3b-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' '\n \n \t\tgit checkout A^0 &&\n \n+\t\ttest_path_is_missing bar/bq &&\n \t\tGIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&\n \n-\t\ttest_i18ngrep ! \"Skipped bar/bq\" out &&\n \t\ttest_must_be_empty err &&\n \n+\t\ttest_path_is_file bar/bq &&\n+\n \t\tgit ls-files -s >index_files &&\n \t\ttest_line_count = 2 index_files &&\n \n@@ -580,11 +603,13 @@ test_expect_success '3b-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' '\n \n \t\tgit checkout B^0 &&\n \n+\t\ttest_path_is_missing bar/bq &&\n \t\tGIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err &&\n \n-\t\ttest_i18ngrep ! \"Skipped bar/bq\" out &&\n \t\ttest_must_be_empty err &&\n \n+\t\ttest_path_is_file bar/bq &&\n+\n \t\tgit ls-files -s >index_files &&\n \t\ttest_line_count = 2 index_files &&\n \n@@ -654,16 +679,16 @@ test_expect_failure '4a: Change on A, change on B subset of A, dirty mods presen\n \t\tgit checkout A^0 &&\n \t\techo \"File rewritten\" >b &&\n \n-\t\ttest-tool chmtime =31337 b &&\n-\t\ttest-tool chmtime -v +0 b >expected-mtime &&\n+\t\ttest-tool chmtime =-1 b &&\n+\t\ttest-tool chmtime --get b >old-mtime &&\n \n \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&\n \n-\t\ttest_i18ngrep \"Skipped b\" out &&\n \t\ttest_must_be_empty err &&\n \n-\t\ttest-tool chmtime -v +0 b >actual-mtime &&\n-\t\ttest_cmp expected-mtime actual-mtime &&\n+\t\t# Make sure b was NOT updated\n+\t\ttest-tool chmtime --get b >new-mtime &&\n+\t\ttest_cmp old-mtime new-mtime &&\n \n \t\tgit ls-files -s >index_files &&\n \t\ttest_line_count = 1 index_files &&\n@@ -722,16 +747,16 @@ test_expect_success '4b: Rename+Mod(A)/Mod(B), change on B subset of A, dirty mo\n \t\tgit checkout A^0 &&\n \t\techo \"File rewritten\" >c &&\n \n-\t\ttest-tool chmtime =31337 c &&\n-\t\ttest-tool chmtime -v +0 c >expected-mtime &&\n+\t\ttest-tool chmtime =-1 c &&\n+\t\ttest-tool chmtime --get c >old-mtime &&\n \n \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&\n \n-\t\ttest_i18ngrep \"Skipped c\" out &&\n \t\ttest_must_be_empty err &&\n \n-\t\ttest-tool chmtime -v +0 c >actual-mtime &&\n-\t\ttest_cmp expected-mtime actual-mtime &&\n+\t\t# Make sure c was NOT updated\n+\t\ttest-tool chmtime --get c >new-mtime &&\n+\t\ttest_cmp old-mtime new-mtime &&\n \n \t\tgit ls-files -s >index_files &&\n \t\ttest_line_count = 1 index_files &&\n-- \ngitgitgadget\n\n"},{"id":"393125","messageId":"20200312132032.GD3122@szeder.dev","threadId":"52895","inReplyTo":"26d0c34cd1d4a54dab28d0c9c2242336244e8a3c.1582762465.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 4/5] t6022, t6046: test expected behavior instead of testing a proxy for it","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2020-03-12T13:20:32Z","receivedAt":"2020-03-12T13:20:41Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Thu, Feb 27, 2020 at 12:14:23AM +0000, Elijah Newren via GitGitGadget wrote:\n> From: Elijah Newren <newren@gmail.com>\n> \n> In t6022, we were testing for file being overwritten (or not) based on\n> an output message instead of checking for the file being overwritten.\n> Since we can check for the file being overwritten via mtime updates,\n> check that instead.\n> \n> In t6046, we were largely checking for both the expected behavior and a\n> proxy for it, which is unnecessary.  The calls to test-tool also were a\n> bit cryptic.  Make them a little clearer.\n> \n> Signed-off-by: Elijah Newren <newren@gmail.com>\n> ---\n>  t/t6022-merge-rename.sh                | 15 ++++-\n>  t/t6046-merge-skip-unneeded-updates.sh | 89 +++++++++++++++++---------\n>  2 files changed, 70 insertions(+), 34 deletions(-)\n> \n> diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh\n> index 6f196aaf276..d97cf48495b 100755\n> --- a/t/t6022-merge-rename.sh\n> +++ b/t/t6022-merge-rename.sh\n> @@ -242,12 +242,23 @@ test_expect_success 'merge of identical changes in a renamed file' '\n>  \trm -f A M N &&\n>  \tgit reset --hard &&\n>  \tgit checkout change+rename &&\n> +\n> +\ttest-tool chmtime =31337 B &&\n> +\ttest-tool chmtime --get B >old-mtime &&\n\nNit: I think it's possible to change the mtime and print it in a\nsingle invocation with:\n\n  test-tool chmtime --get =1234 file\n\n>  \tGIT_MERGE_VERBOSITY=3 git merge change >out &&\n\nNit: The output of 'git merge' is still redirected to a file, but ...\n\n> -\ttest_i18ngrep \"^Skipped B\" out &&\n\n... the only command looking at the output is now removed.\n\n> +\ttest-tool chmtime --get B >new-mtime &&\n> +\ttest_cmp old-mtime new-mtime &&\n> +\n>  \tgit reset --hard HEAD^ &&\n>  \tgit checkout change &&\n> +\n> +\ttest-tool chmtime =-1 M &&\n> +\ttest-tool chmtime --get M >old-mtime &&\n>  \tGIT_MERGE_VERBOSITY=3 git merge change+rename >out &&\n> -\ttest_i18ngrep ! \"^Skipped B\" out\n\nLikewise.\n\n> +\ttest-tool chmtime --get B >new-mtime &&\n> +\ttest $(cat old-mtime) -lt $(cat new-mtime)\n\nI saw this test fail today in one of my custom CI builds:\n\n  +git checkout change\n  Switched to branch 'change'\n  +test-tool chmtime =-1 M\n  +test-tool chmtime --get M\n  +GIT_MERGE_VERBOSITY=3 git merge change+rename\n  +test-tool chmtime --get B\n  +cat old-mtime\n  +cat new-mtime\n  +test 1583967731 -lt 1583967731\n  error: last command exited with $?=1\n  not ok 12 - merge of identical changes in a renamed file\n\nThe contents of 'out', i.e. the output of the 'git merge' command\nbefore the failure is:\n\n  Auto-merging B\n  Merge made by the 'recursive' strategy.\n   A => B | 0\n   1 file changed, 0 insertions(+), 0 deletions(-)\n   rename A => B (100%)\n\nThis is a rare failure, this is the first time I saw it, and to make\nthings worse, this one time it happened on big-endian and with all the\nGIT_TEST_* knobs enabled.\n\n  https://travis-ci.org/github/szeder/git-cooking-topics-for-travis-ci/jobs/661294571#L4020\n\nI've been running './t6022-merge-rename.sh --stress -r 1,12' both with\nand without all the GIT_TEST_* knobs for a few hundred repetitions,\nbut couldn't trigger the failure yet...\n\nI wonder whether comparing the mtimes with '-le' instead of '-lt' is\nacceptable in this test case, but don't have enough insight to form an\nopinion.  Note that this patch added a few similar mtime comparisons\nto t6046 below, and they might be prone to the same issue as well.\n\n>  test_expect_success 'setup for rename + d/f conflicts' '\n> diff --git a/t/t6046-merge-skip-unneeded-updates.sh b/t/t6046-merge-skip-unneeded-updates.sh\n> index b7e46698321..962030ecdb6 100755\n> --- a/t/t6046-merge-skip-unneeded-updates.sh\n> +++ b/t/t6046-merge-skip-unneeded-updates.sh\n> @@ -71,16 +71,16 @@ test_expect_success '1a-L: Modify(A)/Modify(B), change on B subset of A' '\n>  \n>  \t\tgit checkout A^0 &&\n>  \n> -\t\ttest-tool chmtime =31337 b &&\n> -\t\ttest-tool chmtime -v +0 b >expected-mtime &&\n> +\t\ttest-tool chmtime =-1 b &&\n> +\t\ttest-tool chmtime --get b >old-mtime &&\n>  \n>  \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&\n>  \n> -\t\ttest_i18ngrep \"Skipped b\" out &&\n>  \t\ttest_must_be_empty err &&\n>  \n> -\t\ttest-tool chmtime -v +0 b >actual-mtime &&\n> -\t\ttest_cmp expected-mtime actual-mtime &&\n> +\t\t# Make sure b was NOT updated\n> +\t\ttest-tool chmtime --get b >new-mtime &&\n> +\t\ttest_cmp old-mtime new-mtime &&\n>  \n>  \t\tgit ls-files -s >index_files &&\n>  \t\ttest_line_count = 1 index_files &&\n> @@ -102,9 +102,14 @@ test_expect_success '1a-R: Modify(A)/Modify(B), change on B subset of A' '\n>  \n>  \t\tgit checkout B^0 &&\n>  \n> +\t\ttest-tool chmtime =-1 b &&\n> +\t\ttest-tool chmtime --get b >old-mtime &&\n>  \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&\n>  \n> -\t\ttest_i18ngrep \"Auto-merging b\" out &&\n> +\t\t# Make sure b WAS updated\n> +\t\ttest-tool chmtime --get b >new-mtime &&\n> +\t\ttest $(cat old-mtime) -lt $(cat new-mtime) &&\n> +\n>  \t\ttest_must_be_empty err &&\n>  \n>  \t\tgit ls-files -s >index_files &&\n> @@ -165,10 +170,10 @@ test_expect_success '2a-L: Modify/rename, merge into modify side' '\n>  \n>  \t\tgit checkout A^0 &&\n>  \n> +\t\ttest_path_is_missing c &&\n>  \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&\n>  \n> -\t\ttest_i18ngrep ! \"Skipped c\" out &&\n> -\t\ttest_must_be_empty err &&\n> +\t\ttest_path_is_file c &&\n>  \n>  \t\tgit ls-files -s >index_files &&\n>  \t\ttest_line_count = 1 index_files &&\n> @@ -193,9 +198,14 @@ test_expect_success '2a-R: Modify/rename, merge into rename side' '\n>  \n>  \t\tgit checkout B^0 &&\n>  \n> +\t\ttest-tool chmtime =-1 c &&\n> +\t\ttest-tool chmtime --get c >old-mtime &&\n>  \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&\n>  \n> -\t\ttest_i18ngrep ! \"Skipped c\" out &&\n> +\t\t# Make sure c WAS updated\n> +\t\ttest-tool chmtime --get c >new-mtime &&\n> +\t\ttest $(cat old-mtime) -lt $(cat new-mtime) &&\n> +\n>  \t\ttest_must_be_empty err &&\n>  \n>  \t\tgit ls-files -s >index_files &&\n> @@ -256,16 +266,15 @@ test_expect_success '2b-L: Rename+Mod(A)/Mod(B), B mods subset of A' '\n>  \n>  \t\tgit checkout A^0 &&\n>  \n> -\t\ttest-tool chmtime =31337 c &&\n> -\t\ttest-tool chmtime -v +0 c >expected-mtime &&\n> -\n> +\t\ttest-tool chmtime =-1 c &&\n> +\t\ttest-tool chmtime --get c >old-mtime &&\n>  \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&\n>  \n> -\t\ttest_i18ngrep \"Skipped c\" out &&\n>  \t\ttest_must_be_empty err &&\n>  \n> -\t\ttest-tool chmtime -v +0 c >actual-mtime &&\n> -\t\ttest_cmp expected-mtime actual-mtime &&\n> +\t\t# Make sure c WAS updated\n> +\t\ttest-tool chmtime --get c >new-mtime &&\n> +\t\ttest_cmp old-mtime new-mtime &&\n>  \n>  \t\tgit ls-files -s >index_files &&\n>  \t\ttest_line_count = 1 index_files &&\n> @@ -290,9 +299,12 @@ test_expect_success '2b-R: Rename+Mod(A)/Mod(B), B mods subset of A' '\n>  \n>  \t\tgit checkout B^0 &&\n>  \n> +\t\ttest_path_is_missing c &&\n>  \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&\n>  \n> -\t\ttest_i18ngrep \"Auto-merging c\" out &&\n> +\t\t# Make sure c now present (and thus was updated)\n> +\t\ttest_path_is_file c &&\n> +\n>  \t\ttest_must_be_empty err &&\n>  \n>  \t\tgit ls-files -s >index_files &&\n> @@ -361,13 +373,18 @@ test_expect_success '2c: Modify b & add c VS rename b->c' '\n>  \n>  \t\tgit checkout A^0 &&\n>  \n> +\t\ttest-tool chmtime =-1 c &&\n> +\t\ttest-tool chmtime --get c >old-mtime &&\n>  \t\tGIT_MERGE_VERBOSITY=3 &&\n>  \t\texport GIT_MERGE_VERBOSITY &&\n>  \t\ttest_must_fail git merge -s recursive B^0 >out 2>err &&\n>  \n>  \t\ttest_i18ngrep \"CONFLICT (rename/add): Rename b->c\" out &&\n> -\t\ttest_i18ngrep ! \"Skipped c\" out &&\n> -\t\ttest_must_be_empty err\n> +\t\ttest_must_be_empty err &&\n> +\n> +\t\t# Make sure c WAS updated\n> +\t\ttest-tool chmtime --get c >new-mtime &&\n> +\t\ttest $(cat old-mtime) -lt $(cat new-mtime)\n>  \n>  \t\t# FIXME: rename/add conflicts are horribly broken right now;\n>  \t\t# when I get back to my patch series fixing it and\n> @@ -460,11 +477,13 @@ test_expect_success '3a-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' '\n>  \n>  \t\tgit checkout A^0 &&\n>  \n> +\t\ttest_path_is_missing bar/bq &&\n>  \t\tGIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&\n>  \n> -\t\ttest_i18ngrep ! \"Skipped bar/bq\" out &&\n>  \t\ttest_must_be_empty err &&\n>  \n> +\t\ttest_path_is_file bar/bq &&\n> +\n>  \t\tgit ls-files -s >index_files &&\n>  \t\ttest_line_count = 2 index_files &&\n>  \n> @@ -488,11 +507,13 @@ test_expect_success '3a-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' '\n>  \n>  \t\tgit checkout B^0 &&\n>  \n> +\t\ttest_path_is_missing bar/bq &&\n>  \t\tGIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err &&\n>  \n> -\t\ttest_i18ngrep ! \"Skipped bar/bq\" out &&\n>  \t\ttest_must_be_empty err &&\n>  \n> +\t\ttest_path_is_file bar/bq &&\n> +\n>  \t\tgit ls-files -s >index_files &&\n>  \t\ttest_line_count = 2 index_files &&\n>  \n> @@ -552,11 +573,13 @@ test_expect_success '3b-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' '\n>  \n>  \t\tgit checkout A^0 &&\n>  \n> +\t\ttest_path_is_missing bar/bq &&\n>  \t\tGIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&\n>  \n> -\t\ttest_i18ngrep ! \"Skipped bar/bq\" out &&\n>  \t\ttest_must_be_empty err &&\n>  \n> +\t\ttest_path_is_file bar/bq &&\n> +\n>  \t\tgit ls-files -s >index_files &&\n>  \t\ttest_line_count = 2 index_files &&\n>  \n> @@ -580,11 +603,13 @@ test_expect_success '3b-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' '\n>  \n>  \t\tgit checkout B^0 &&\n>  \n> +\t\ttest_path_is_missing bar/bq &&\n>  \t\tGIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err &&\n>  \n> -\t\ttest_i18ngrep ! \"Skipped bar/bq\" out &&\n>  \t\ttest_must_be_empty err &&\n>  \n> +\t\ttest_path_is_file bar/bq &&\n> +\n>  \t\tgit ls-files -s >index_files &&\n>  \t\ttest_line_count = 2 index_files &&\n>  \n> @@ -654,16 +679,16 @@ test_expect_failure '4a: Change on A, change on B subset of A, dirty mods presen\n>  \t\tgit checkout A^0 &&\n>  \t\techo \"File rewritten\" >b &&\n>  \n> -\t\ttest-tool chmtime =31337 b &&\n> -\t\ttest-tool chmtime -v +0 b >expected-mtime &&\n> +\t\ttest-tool chmtime =-1 b &&\n> +\t\ttest-tool chmtime --get b >old-mtime &&\n>  \n>  \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&\n>  \n> -\t\ttest_i18ngrep \"Skipped b\" out &&\n>  \t\ttest_must_be_empty err &&\n>  \n> -\t\ttest-tool chmtime -v +0 b >actual-mtime &&\n> -\t\ttest_cmp expected-mtime actual-mtime &&\n> +\t\t# Make sure b was NOT updated\n> +\t\ttest-tool chmtime --get b >new-mtime &&\n> +\t\ttest_cmp old-mtime new-mtime &&\n>  \n>  \t\tgit ls-files -s >index_files &&\n>  \t\ttest_line_count = 1 index_files &&\n> @@ -722,16 +747,16 @@ test_expect_success '4b: Rename+Mod(A)/Mod(B), change on B subset of A, dirty mo\n>  \t\tgit checkout A^0 &&\n>  \t\techo \"File rewritten\" >c &&\n>  \n> -\t\ttest-tool chmtime =31337 c &&\n> -\t\ttest-tool chmtime -v +0 c >expected-mtime &&\n> +\t\ttest-tool chmtime =-1 c &&\n> +\t\ttest-tool chmtime --get c >old-mtime &&\n>  \n>  \t\tGIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&\n>  \n> -\t\ttest_i18ngrep \"Skipped c\" out &&\n>  \t\ttest_must_be_empty err &&\n>  \n> -\t\ttest-tool chmtime -v +0 c >actual-mtime &&\n> -\t\ttest_cmp expected-mtime actual-mtime &&\n> +\t\t# Make sure c was NOT updated\n> +\t\ttest-tool chmtime --get c >new-mtime &&\n> +\t\ttest_cmp old-mtime new-mtime &&\n>  \n>  \t\tgit ls-files -s >index_files &&\n>  \t\ttest_line_count = 1 index_files &&\n> -- \n> gitgitgadget\n> \n"},{"id":"393137","messageId":"CABPp-BEa7pvqgH+EytGPp2AO5nBmEgW0+7HnjK-e3MqrBnthnA@mail.gmail.com","threadId":"52895","inReplyTo":"20200312132032.GD3122@szeder.dev","subject":"Re: [PATCH 4/5] t6022, t6046: test expected behavior instead of testing a proxy for it","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-03-12T16:48:01Z","receivedAt":"2020-03-12T16:48:14Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Thu, Mar 12, 2020 at 6:20 AM SZEDER Gábor <szeder.dev@gmail.com> wrote:\n>\n> On Thu, Feb 27, 2020 at 12:14:23AM +0000, Elijah Newren via GitGitGadget wrote:\n> > From: Elijah Newren <newren@gmail.com>\n> >\n> > In t6022, we were testing for file being overwritten (or not) based on\n> > an output message instead of checking for the file being overwritten.\n> > Since we can check for the file being overwritten via mtime updates,\n> > check that instead.\n> >\n> > In t6046, we were largely checking for both the expected behavior and a\n> > proxy for it, which is unnecessary.  The calls to test-tool also were a\n> > bit cryptic.  Make them a little clearer.\n> >\n> > Signed-off-by: Elijah Newren <newren@gmail.com>\n> > ---\n> >  t/t6022-merge-rename.sh                | 15 ++++-\n> >  t/t6046-merge-skip-unneeded-updates.sh | 89 +++++++++++++++++---------\n> >  2 files changed, 70 insertions(+), 34 deletions(-)\n> >\n> > diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh\n> > index 6f196aaf276..d97cf48495b 100755\n> > --- a/t/t6022-merge-rename.sh\n> > +++ b/t/t6022-merge-rename.sh\n> > @@ -242,12 +242,23 @@ test_expect_success 'merge of identical changes in a renamed file' '\n> >       rm -f A M N &&\n> >       git reset --hard &&\n> >       git checkout change+rename &&\n> > +\n> > +     test-tool chmtime =31337 B &&\n> > +     test-tool chmtime --get B >old-mtime &&\n>\n> Nit: I think it's possible to change the mtime and print it in a\n> single invocation with:\n>\n>   test-tool chmtime --get =1234 file\n\nOh, cool.\n\n> >       GIT_MERGE_VERBOSITY=3 git merge change >out &&\n>\n> Nit: The output of 'git merge' is still redirected to a file, but ...\n>\n> > -     test_i18ngrep \"^Skipped B\" out &&\n>\n> ... the only command looking at the output is now removed.\n\nIndeed.\n\n> > +     test-tool chmtime --get B >new-mtime &&\n> > +     test_cmp old-mtime new-mtime &&\n> > +\n> >       git reset --hard HEAD^ &&\n> >       git checkout change &&\n> > +\n> > +     test-tool chmtime =-1 M &&\n> > +     test-tool chmtime --get M >old-mtime &&\n> >       GIT_MERGE_VERBOSITY=3 git merge change+rename >out &&\n> > -     test_i18ngrep ! \"^Skipped B\" out\n>\n> Likewise.\n>\n> > +     test-tool chmtime --get B >new-mtime &&\n> > +     test $(cat old-mtime) -lt $(cat new-mtime)\n>\n> I saw this test fail today in one of my custom CI builds:\n>\n>   +git checkout change\n>   Switched to branch 'change'\n>   +test-tool chmtime =-1 M\n>   +test-tool chmtime --get M\n>   +GIT_MERGE_VERBOSITY=3 git merge change+rename\n>   +test-tool chmtime --get B\n>   +cat old-mtime\n>   +cat new-mtime\n>   +test 1583967731 -lt 1583967731\n>   error: last command exited with $?=1\n>   not ok 12 - merge of identical changes in a renamed file\n>\n> The contents of 'out', i.e. the output of the 'git merge' command\n> before the failure is:\n>\n>   Auto-merging B\n>   Merge made by the 'recursive' strategy.\n>    A => B | 0\n>    1 file changed, 0 insertions(+), 0 deletions(-)\n>    rename A => B (100%)\n>\n> This is a rare failure, this is the first time I saw it, and to make\n> things worse, this one time it happened on big-endian and with all the\n> GIT_TEST_* knobs enabled.\n>\n>   https://travis-ci.org/github/szeder/git-cooking-topics-for-travis-ci/jobs/661294571#L4020\n\nThis is very troubling.  The workflow is basically:\n  - Manually set the mtime to a file to something old (I happened to\npick 1 second before now, but picking something from 1970 would have\nbeen fine too).\n  - Run a merge which is known to need to overwrite the file.  Your\noutput (\"Auto-merging B\") suggests that we should have been in such a\ncase.\n  - Verify that the file was actually updated as expected.  Since the\nOS is supposed to update the mtime when it writes the file, it should\nhave set it to something recent, i.e. something *different* than what\nit had before.\n\nSo, now I'm left wondering how the mtime possibly could have been not\nupdated.  Maybe the file wasn't actually written?  (But if so, why\ndidn't other people see the failure?  Or your stress runs not see it?)\n Or maybe it was written but all file contents and metadata were\ndelayed in writing to disk such that a subsequent command still sees\nthe old file??  Or maybe it was written but the mtime update was\ndelayed and the test was able to check it in that intermediate\nstate???  Or perhaps the mtime check before the merge raced with the\nsetting of the mtime backwards and got the mtime before it was\nrewound????\n\nI don't have a plausible scenario under which any of these should be\npossible; I'm at a loss.\n\n> I've been running './t6022-merge-rename.sh --stress -r 1,12' both with\n> and without all the GIT_TEST_* knobs for a few hundred repetitions,\n> but couldn't trigger the failure yet...\n\nI'm not sure if that makes me feel better or worse.\n\n> I wonder whether comparing the mtimes with '-le' instead of '-lt' is\n> acceptable in this test case, but don't have enough insight to form an\n> opinion.  Note that this patch added a few similar mtime comparisons\n> to t6046 below, and they might be prone to the same issue as well.\n\n-le would not be acceptable; if we were to do that we may as well\nthrow away the test.  The test exists to check that the file contents\nwere actually written, which I was assuming could be verified by an\nmtime update of what otherwise used to be an \"old\" file.\n"},{"id":"393146","messageId":"CABPp-BGR_eDHJmNOPVQLx8WkL5WLV6J0NtQJ2=AE7CQB2sck5g@mail.gmail.com","threadId":"52895","inReplyTo":"CABPp-BEa7pvqgH+EytGPp2AO5nBmEgW0+7HnjK-e3MqrBnthnA@mail.gmail.com","subject":"Re: [PATCH 4/5] t6022, t6046: test expected behavior instead of testing a proxy for it","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-03-12T17:35:52Z","receivedAt":"2020-03-12T17:36:05Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Thu, Mar 12, 2020 at 9:48 AM Elijah Newren <newren@gmail.com> wrote:\n>\n> On Thu, Mar 12, 2020 at 6:20 AM SZEDER Gábor <szeder.dev@gmail.com> wrote:\n> >\n> > On Thu, Feb 27, 2020 at 12:14:23AM +0000, Elijah Newren via GitGitGadget wrote:\n> > > From: Elijah Newren <newren@gmail.com>\n> > >\n> > > In t6022, we were testing for file being overwritten (or not) based on\n> > > an output message instead of checking for the file being overwritten.\n> > > Since we can check for the file being overwritten via mtime updates,\n> > > check that instead.\n> > >\n> > > In t6046, we were largely checking for both the expected behavior and a\n> > > proxy for it, which is unnecessary.  The calls to test-tool also were a\n> > > bit cryptic.  Make them a little clearer.\n> > >\n> > > Signed-off-by: Elijah Newren <newren@gmail.com>\n> > > ---\n> > >  t/t6022-merge-rename.sh                | 15 ++++-\n> > >  t/t6046-merge-skip-unneeded-updates.sh | 89 +++++++++++++++++---------\n> > >  2 files changed, 70 insertions(+), 34 deletions(-)\n> > >\n> > > diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh\n> > > index 6f196aaf276..d97cf48495b 100755\n> > > --- a/t/t6022-merge-rename.sh\n> > > +++ b/t/t6022-merge-rename.sh\n> > > @@ -242,12 +242,23 @@ test_expect_success 'merge of identical changes in a renamed file' '\n> > >       rm -f A M N &&\n> > >       git reset --hard &&\n> > >       git checkout change+rename &&\n> > > +\n> > > +     test-tool chmtime =31337 B &&\n> > > +     test-tool chmtime --get B >old-mtime &&\n> >\n> > Nit: I think it's possible to change the mtime and print it in a\n> > single invocation with:\n> >\n> >   test-tool chmtime --get =1234 file\n>\n> Oh, cool.\n>\n> > >       GIT_MERGE_VERBOSITY=3 git merge change >out &&\n> >\n> > Nit: The output of 'git merge' is still redirected to a file, but ...\n> >\n> > > -     test_i18ngrep \"^Skipped B\" out &&\n> >\n> > ... the only command looking at the output is now removed.\n>\n> Indeed.\n>\n> > > +     test-tool chmtime --get B >new-mtime &&\n> > > +     test_cmp old-mtime new-mtime &&\n> > > +\n> > >       git reset --hard HEAD^ &&\n> > >       git checkout change &&\n> > > +\n> > > +     test-tool chmtime =-1 M &&\n> > > +     test-tool chmtime --get M >old-mtime &&\n> > >       GIT_MERGE_VERBOSITY=3 git merge change+rename >out &&\n> > > -     test_i18ngrep ! \"^Skipped B\" out\n> >\n> > Likewise.\n> >\n> > > +     test-tool chmtime --get B >new-mtime &&\n> > > +     test $(cat old-mtime) -lt $(cat new-mtime)\n> >\n> > I saw this test fail today in one of my custom CI builds:\n> >\n> >   +git checkout change\n> >   Switched to branch 'change'\n> >   +test-tool chmtime =-1 M\n> >   +test-tool chmtime --get M\n> >   +GIT_MERGE_VERBOSITY=3 git merge change+rename\n> >   +test-tool chmtime --get B\n> >   +cat old-mtime\n> >   +cat new-mtime\n> >   +test 1583967731 -lt 1583967731\n> >   error: last command exited with $?=1\n> >   not ok 12 - merge of identical changes in a renamed file\n> >\n> > The contents of 'out', i.e. the output of the 'git merge' command\n> > before the failure is:\n> >\n> >   Auto-merging B\n> >   Merge made by the 'recursive' strategy.\n> >    A => B | 0\n> >    1 file changed, 0 insertions(+), 0 deletions(-)\n> >    rename A => B (100%)\n> >\n> > This is a rare failure, this is the first time I saw it, and to make\n> > things worse, this one time it happened on big-endian and with all the\n> > GIT_TEST_* knobs enabled.\n> >\n> >   https://travis-ci.org/github/szeder/git-cooking-topics-for-travis-ci/jobs/661294571#L4020\n>\n> This is very troubling.  The workflow is basically:\n>   - Manually set the mtime to a file to something old (I happened to\n> pick 1 second before now, but picking something from 1970 would have\n> been fine too).\n>   - Run a merge which is known to need to overwrite the file.  Your\n> output (\"Auto-merging B\") suggests that we should have been in such a\n> case.\n>   - Verify that the file was actually updated as expected.  Since the\n> OS is supposed to update the mtime when it writes the file, it should\n> have set it to something recent, i.e. something *different* than what\n> it had before.\n>\n> So, now I'm left wondering how the mtime possibly could have been not\n> updated.  Maybe the file wasn't actually written?  (But if so, why\n> didn't other people see the failure?  Or your stress runs not see it?)\n>  Or maybe it was written but all file contents and metadata were\n> delayed in writing to disk such that a subsequent command still sees\n> the old file??  Or maybe it was written but the mtime update was\n> delayed and the test was able to check it in that intermediate\n> state???  Or perhaps the mtime check before the merge raced with the\n> setting of the mtime backwards and got the mtime before it was\n> rewound????\n>\n> I don't have a plausible scenario under which any of these should be\n> possible; I'm at a loss.\n\nHmm.  Maybe leap seconds, or clock updates via ntp at an unfortunate\ntime?  Perhaps just setting the \"old\" time to something more than one\nsecond in the past would avoid this?\n\nAnyone have a clue if this is a useful guess or not?\n"},{"id":"393168","messageId":"20200312200157.GE3122@szeder.dev","threadId":"52895","inReplyTo":"CABPp-BGR_eDHJmNOPVQLx8WkL5WLV6J0NtQJ2=AE7CQB2sck5g@mail.gmail.com","subject":"Re: [PATCH 4/5] t6022, t6046: test expected behavior instead of testing a proxy for it","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2020-03-12T20:01:57Z","receivedAt":"2020-03-12T20:02:05Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Thu, Mar 12, 2020 at 10:35:52AM -0700, Elijah Newren wrote:\n> On Thu, Mar 12, 2020 at 9:48 AM Elijah Newren <newren@gmail.com> wrote:\n> >\n> > On Thu, Mar 12, 2020 at 6:20 AM SZEDER Gábor <szeder.dev@gmail.com> wrote:\n> > >\n> > > On Thu, Feb 27, 2020 at 12:14:23AM +0000, Elijah Newren via GitGitGadget wrote:\n> > > > From: Elijah Newren <newren@gmail.com>\n> > > >\n> > > > In t6022, we were testing for file being overwritten (or not) based on\n> > > > an output message instead of checking for the file being overwritten.\n> > > > Since we can check for the file being overwritten via mtime updates,\n> > > > check that instead.\n> > > >\n> > > > In t6046, we were largely checking for both the expected behavior and a\n> > > > proxy for it, which is unnecessary.  The calls to test-tool also were a\n> > > > bit cryptic.  Make them a little clearer.\n> > > >\n> > > > Signed-off-by: Elijah Newren <newren@gmail.com>\n> > > > ---\n> > > >  t/t6022-merge-rename.sh                | 15 ++++-\n> > > >  t/t6046-merge-skip-unneeded-updates.sh | 89 +++++++++++++++++---------\n> > > >  2 files changed, 70 insertions(+), 34 deletions(-)\n> > > >\n> > > > diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh\n> > > > index 6f196aaf276..d97cf48495b 100755\n> > > > --- a/t/t6022-merge-rename.sh\n> > > > +++ b/t/t6022-merge-rename.sh\n> > > > @@ -242,12 +242,23 @@ test_expect_success 'merge of identical changes in a renamed file' '\n> > > >       rm -f A M N &&\n> > > >       git reset --hard &&\n> > > >       git checkout change+rename &&\n> > > > +\n> > > > +     test-tool chmtime =31337 B &&\n> > > > +     test-tool chmtime --get B >old-mtime &&\n> > >\n> > > Nit: I think it's possible to change the mtime and print it in a\n> > > single invocation with:\n> > >\n> > >   test-tool chmtime --get =1234 file\n> >\n> > Oh, cool.\n> >\n> > > >       GIT_MERGE_VERBOSITY=3 git merge change >out &&\n> > >\n> > > Nit: The output of 'git merge' is still redirected to a file, but ...\n> > >\n> > > > -     test_i18ngrep \"^Skipped B\" out &&\n> > >\n> > > ... the only command looking at the output is now removed.\n> >\n> > Indeed.\n> >\n> > > > +     test-tool chmtime --get B >new-mtime &&\n> > > > +     test_cmp old-mtime new-mtime &&\n> > > > +\n> > > >       git reset --hard HEAD^ &&\n> > > >       git checkout change &&\n> > > > +\n> > > > +     test-tool chmtime =-1 M &&\n> > > > +     test-tool chmtime --get M >old-mtime &&\n> > > >       GIT_MERGE_VERBOSITY=3 git merge change+rename >out &&\n> > > > -     test_i18ngrep ! \"^Skipped B\" out\n> > >\n> > > Likewise.\n> > >\n> > > > +     test-tool chmtime --get B >new-mtime &&\n> > > > +     test $(cat old-mtime) -lt $(cat new-mtime)\n> > >\n> > > I saw this test fail today in one of my custom CI builds:\n> > >\n> > >   +git checkout change\n> > >   Switched to branch 'change'\n> > >   +test-tool chmtime =-1 M\n> > >   +test-tool chmtime --get M\n> > >   +GIT_MERGE_VERBOSITY=3 git merge change+rename\n> > >   +test-tool chmtime --get B\n> > >   +cat old-mtime\n> > >   +cat new-mtime\n> > >   +test 1583967731 -lt 1583967731\n> > >   error: last command exited with $?=1\n> > >   not ok 12 - merge of identical changes in a renamed file\n> > >\n> > > The contents of 'out', i.e. the output of the 'git merge' command\n> > > before the failure is:\n> > >\n> > >   Auto-merging B\n> > >   Merge made by the 'recursive' strategy.\n> > >    A => B | 0\n> > >    1 file changed, 0 insertions(+), 0 deletions(-)\n> > >    rename A => B (100%)\n> > >\n> > > This is a rare failure, this is the first time I saw it, and to make\n> > > things worse, this one time it happened on big-endian and with all the\n> > > GIT_TEST_* knobs enabled.\n> > >\n> > >   https://travis-ci.org/github/szeder/git-cooking-topics-for-travis-ci/jobs/661294571#L4020\n> >\n> > This is very troubling.  The workflow is basically:\n> >   - Manually set the mtime to a file to something old (I happened to\n> > pick 1 second before now, but picking something from 1970 would have\n> > been fine too).\n> >   - Run a merge which is known to need to overwrite the file.  Your\n> > output (\"Auto-merging B\") suggests that we should have been in such a\n> > case.\n> >   - Verify that the file was actually updated as expected.  Since the\n> > OS is supposed to update the mtime when it writes the file, it should\n> > have set it to something recent, i.e. something *different* than what\n> > it had before.\n> >\n> > So, now I'm left wondering how the mtime possibly could have been not\n> > updated.  Maybe the file wasn't actually written?  (But if so, why\n> > didn't other people see the failure?  Or your stress runs not see it?)\n> >  Or maybe it was written but all file contents and metadata were\n> > delayed in writing to disk such that a subsequent command still sees\n> > the old file??  Or maybe it was written but the mtime update was\n> > delayed and the test was able to check it in that intermediate\n> > state???  Or perhaps the mtime check before the merge raced with the\n> > setting of the mtime backwards and got the mtime before it was\n> > rewound????\n> >\n> > I don't have a plausible scenario under which any of these should be\n> > possible; I'm at a loss.\n> \n> Hmm.  Maybe leap seconds, or clock updates via ntp at an unfortunate\n> time?\n\nI'm now fairly confident that 'git merge' is OK, and suspect that it's\nan issue with Travis CI's s390x environment (multi-architecture\nsupport is an alpha-stage feature).\n\nI kicked off a build that only runs 't6022 --stress -r 1,12', and it\nfailed with the same error on s390x fairly quickly, but haven't failed\nin any of our \"standard\" CI jobs until the jobs timeouted.\n\n  https://travis-ci.org/github/szeder/git/jobs/661647673#L2084\n\nThen I kicked off a build to run the test below with --stress:\n\n  test_expect_success 'test' '\n  \ttouch file &&\n  \told=$(test-tool chmtime --get =-1 file) &&\n  \ttouch file &&\n  \tnew=$(test-tool chmtime --get file) &&\n  \ttest $old -lt $new\n  '\n\nThis failed fairly quickly with the same error on s390x as well.\n\n  https://travis-ci.org/github/szeder/git/jobs/661654844#L1275\n\nSo I think 'git merge' should be okay, because the failure could be\ntriggered without it as well.\n\n> Perhaps just setting the \"old\" time to something more than one\n> second in the past would avoid this?\n> \n> Anyone have a clue if this is a useful guess or not?\n\nI kicked off a build where I set an older timestamp ('=-10' instead of\n'=-1'), to see what happens, but the s390x job in that build just\ndoesn't want to start...  (alpha feature? :)  Anyway, the job's output\nshould eventually be available here, will try to check back tomorrow:\n\n  https://travis-ci.org/github/szeder/git/jobs/661657781\n\n"},{"id":"393211","messageId":"20200313171248.GA613@szeder.dev","threadId":"52895","inReplyTo":"26d0c34cd1d4a54dab28d0c9c2242336244e8a3c.1582762465.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 4/5] t6022, t6046: test expected behavior instead of testing a proxy for it","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2020-03-13T17:12:48Z","receivedAt":"2020-03-13T17:12:58Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Thu, Feb 27, 2020 at 12:14:23AM +0000, Elijah Newren via GitGitGadget wrote:\n> diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh\n> index 6f196aaf276..d97cf48495b 100755\n> --- a/t/t6022-merge-rename.sh\n> +++ b/t/t6022-merge-rename.sh\n> @@ -242,12 +242,23 @@ test_expect_success 'merge of identical changes in a renamed file' '\n>  \trm -f A M N &&\n>  \tgit reset --hard &&\n>  \tgit checkout change+rename &&\n> +\n> +\ttest-tool chmtime =31337 B &&\n> +\ttest-tool chmtime --get B >old-mtime &&\n\nHere you compare the mtime of 'B' before ...\n\n>  \tGIT_MERGE_VERBOSITY=3 git merge change >out &&\n> -\ttest_i18ngrep \"^Skipped B\" out &&\n> +\n> +\ttest-tool chmtime --get B >new-mtime &&\n> +\ttest_cmp old-mtime new-mtime &&\n\n... and after the merge.\n\n> +\n>  \tgit reset --hard HEAD^ &&\n>  \tgit checkout change &&\n> +\n> +\ttest-tool chmtime =-1 M &&\n> +\ttest-tool chmtime --get M >old-mtime &&\n\nHere, however, you compare the mtime of 'M' before the merge ...\n\n>  \tGIT_MERGE_VERBOSITY=3 git merge change+rename >out &&\n> -\ttest_i18ngrep ! \"^Skipped B\" out\n> +\n> +\ttest-tool chmtime --get B >new-mtime &&\n> +\ttest $(cat old-mtime) -lt $(cat new-mtime)\n\n... with the mtime of 'B' after the merge, i.e. the mtimes of two\ndifferent files.\n\nIs that right?\n\n"},{"id":"393212","messageId":"20200313171739.GF3122@szeder.dev","threadId":"52895","inReplyTo":"20200312200157.GE3122@szeder.dev","subject":"Re: [PATCH 4/5] t6022, t6046: test expected behavior instead of testing a proxy for it","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2020-03-13T17:17:39Z","receivedAt":"2020-03-13T17:17:46Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Thu, Mar 12, 2020 at 09:01:57PM +0100, SZEDER Gábor wrote:\n> > > > I saw this test fail today in one of my custom CI builds:\n> > > >\n> > > >   +git checkout change\n> > > >   Switched to branch 'change'\n> > > >   +test-tool chmtime =-1 M\n> > > >   +test-tool chmtime --get M\n> > > >   +GIT_MERGE_VERBOSITY=3 git merge change+rename\n> > > >   +test-tool chmtime --get B\n> > > >   +cat old-mtime\n> > > >   +cat new-mtime\n> > > >   +test 1583967731 -lt 1583967731\n> > > >   error: last command exited with $?=1\n> > > >   not ok 12 - merge of identical changes in a renamed file\n> > > >\n> > > > The contents of 'out', i.e. the output of the 'git merge' command\n> > > > before the failure is:\n> > > >\n> > > >   Auto-merging B\n> > > >   Merge made by the 'recursive' strategy.\n> > > >    A => B | 0\n> > > >    1 file changed, 0 insertions(+), 0 deletions(-)\n> > > >    rename A => B (100%)\n> > > >\n> > > > This is a rare failure, this is the first time I saw it, and to make\n> > > > things worse, this one time it happened on big-endian and with all the\n> > > > GIT_TEST_* knobs enabled.\n> > > >\n> > > >   https://travis-ci.org/github/szeder/git-cooking-topics-for-travis-ci/jobs/661294571#L4020\n> > >\n> > > This is very troubling.  The workflow is basically:\n> > >   - Manually set the mtime to a file to something old (I happened to\n> > > pick 1 second before now, but picking something from 1970 would have\n> > > been fine too).\n> > >   - Run a merge which is known to need to overwrite the file.  Your\n> > > output (\"Auto-merging B\") suggests that we should have been in such a\n> > > case.\n> > >   - Verify that the file was actually updated as expected.  Since the\n> > > OS is supposed to update the mtime when it writes the file, it should\n> > > have set it to something recent, i.e. something *different* than what\n> > > it had before.\n> > >\n> > > So, now I'm left wondering how the mtime possibly could have been not\n> > > updated.  Maybe the file wasn't actually written?  (But if so, why\n> > > didn't other people see the failure?  Or your stress runs not see it?)\n> > >  Or maybe it was written but all file contents and metadata were\n> > > delayed in writing to disk such that a subsequent command still sees\n> > > the old file??  Or maybe it was written but the mtime update was\n> > > delayed and the test was able to check it in that intermediate\n> > > state???  Or perhaps the mtime check before the merge raced with the\n> > > setting of the mtime backwards and got the mtime before it was\n> > > rewound????\n> > >\n> > > I don't have a plausible scenario under which any of these should be\n> > > possible; I'm at a loss.\n> > \n> > Hmm.  Maybe leap seconds, or clock updates via ntp at an unfortunate\n> > time?\n> \n> I'm now fairly confident that 'git merge' is OK, and suspect that it's\n> an issue with Travis CI's s390x environment (multi-architecture\n> support is an alpha-stage feature).\n\nI could finally reproduce the issue on my own machine, so apparently\nit's not an issue in Travis CI's multi-arch environments.\n\n>   test_expect_success 'test' '\n>   \ttouch file &&\n>   \told=$(test-tool chmtime --get =-1 file) &&\n>   \ttouch file &&\n>   \tnew=$(test-tool chmtime --get file) &&\n>   \ttest $old -lt $new\n>   '\n\nI wanted to report the issue to Travis CI, and in order to do so I\nturned the above test case into a script that doesn't at all depend on\nout test framework and 'test-tool' but uses only coreutils commands\n(with a whole lot of GNUisms...):\n\n  cat >timestamp.sh <<-\\EOF\n  #!/bin/sh\n  \n  set -ex\n  \n  i=0\n  while true\n  do\n  \tprintf \"$i\\r\"\n  \ti=$((i + 1))\n  \n  \t# set a file's mtime to one second ago\n  \tnow=$(date \"+%s.%N\")\n  \tone_sec_ago=$(date -d \"@$((${now%.*} - 1))\" \"+%Y%m%d%H%M%S\")\n  \ttouch -t ${one_sec_ago%??}.${one_sec_ago#????????????} file\n  \t# save its actual mtime\n  \told=$(date -r file \"+%s.%N\")\n  \t# set its mtime to now\n  \ttouch file\n  \t# the current the mtime should be different, but sometimes it isn't\n  \tnew=$(date -r file \"+%s.%N\")\n  \ttest \"${old%.*}\" != \"${new%.*}\"\n  done\n  EOF\n  chmod u+x timestamp.sh\n  ./timestamp.sh 2>out\n  echo\n  tail -n11 out\n\nAnd this script usually fails after a few hundred iterations on my\nmachine:\n\n  308\n  + date +%s.%N\n  + now=1584118408.002458987\n  + date -d @1584118407 +%Y%m%d%H%M%S\n  + one_sec_ago=20200313175327\n  + touch -t 202003131753.27 file\n  + date -r file +%s.%N\n  + old=1584118407.000000000\n  + touch file\n  + date -r file +%s.%N\n  + new=1584118407.997464837\n  + test 1584118407 != 1584118407\n\nNote that the mtime update at the end of the iteration results in an\nmtime that is _before_ the current time at the beginning of the\niteration.  Well, I'm puzzled :)\n\n> > Perhaps just setting the \"old\" time to something more than one\n> > second in the past would avoid this?\n\nYes, setting the old timestamp 2 seconds in the past seems to be\nsufficient, at least I haven't seen it fail in a few 100k repetitions.\n\n"},{"id":"393213","messageId":"CABPp-BGt4xaqG+3m3q=PfMTmfotjvze2TPp5JhthE2YHsLa=-Q@mail.gmail.com","threadId":"52895","inReplyTo":"20200313171248.GA613@szeder.dev","subject":"Re: [PATCH 4/5] t6022, t6046: test expected behavior instead of testing a proxy for it","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-03-13T17:18:29Z","receivedAt":"2020-03-13T17:18:44Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Fri, Mar 13, 2020 at 10:12 AM SZEDER Gábor <szeder.dev@gmail.com> wrote:\n>\n> On Thu, Feb 27, 2020 at 12:14:23AM +0000, Elijah Newren via GitGitGadget wrote:\n> > diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh\n> > index 6f196aaf276..d97cf48495b 100755\n> > --- a/t/t6022-merge-rename.sh\n> > +++ b/t/t6022-merge-rename.sh\n> > @@ -242,12 +242,23 @@ test_expect_success 'merge of identical changes in a renamed file' '\n> >       rm -f A M N &&\n> >       git reset --hard &&\n> >       git checkout change+rename &&\n> > +\n> > +     test-tool chmtime =31337 B &&\n> > +     test-tool chmtime --get B >old-mtime &&\n>\n> Here you compare the mtime of 'B' before ...\n>\n> >       GIT_MERGE_VERBOSITY=3 git merge change >out &&\n> > -     test_i18ngrep \"^Skipped B\" out &&\n> > +\n> > +     test-tool chmtime --get B >new-mtime &&\n> > +     test_cmp old-mtime new-mtime &&\n>\n> ... and after the merge.\n>\n> > +\n> >       git reset --hard HEAD^ &&\n> >       git checkout change &&\n> > +\n> > +     test-tool chmtime =-1 M &&\n> > +     test-tool chmtime --get M >old-mtime &&\n>\n> Here, however, you compare the mtime of 'M' before the merge ...\n>\n> >       GIT_MERGE_VERBOSITY=3 git merge change+rename >out &&\n> > -     test_i18ngrep ! \"^Skipped B\" out\n> > +\n> > +     test-tool chmtime --get B >new-mtime &&\n> > +     test $(cat old-mtime) -lt $(cat new-mtime)\n>\n> ... with the mtime of 'B' after the merge, i.e. the mtimes of two\n> different files.\n>\n> Is that right?\n\nNo, sounds like a copy-and-paste-and-forget-to-update bug.  Thanks for\nspotting it.  Since you found it, do you want to submit a patch with\nthe fix?\n"},{"id":"393214","messageId":"20200313173016.GG3122@szeder.dev","threadId":"52895","inReplyTo":"CABPp-BGt4xaqG+3m3q=PfMTmfotjvze2TPp5JhthE2YHsLa=-Q@mail.gmail.com","subject":"Re: [PATCH 4/5] t6022, t6046: test expected behavior instead of testing a proxy for it","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2020-03-13T17:30:16Z","receivedAt":"2020-03-13T17:30:24Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Fri, Mar 13, 2020 at 10:18:29AM -0700, Elijah Newren wrote:\n> On Fri, Mar 13, 2020 at 10:12 AM SZEDER Gábor <szeder.dev@gmail.com> wrote:\n> >\n> > On Thu, Feb 27, 2020 at 12:14:23AM +0000, Elijah Newren via GitGitGadget wrote:\n> > > diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh\n> > > index 6f196aaf276..d97cf48495b 100755\n> > > --- a/t/t6022-merge-rename.sh\n> > > +++ b/t/t6022-merge-rename.sh\n> > > @@ -242,12 +242,23 @@ test_expect_success 'merge of identical changes in a renamed file' '\n> > >       rm -f A M N &&\n> > >       git reset --hard &&\n> > >       git checkout change+rename &&\n> > > +\n> > > +     test-tool chmtime =31337 B &&\n> > > +     test-tool chmtime --get B >old-mtime &&\n> >\n> > Here you compare the mtime of 'B' before ...\n> >\n> > >       GIT_MERGE_VERBOSITY=3 git merge change >out &&\n> > > -     test_i18ngrep \"^Skipped B\" out &&\n> > > +\n> > > +     test-tool chmtime --get B >new-mtime &&\n> > > +     test_cmp old-mtime new-mtime &&\n> >\n> > ... and after the merge.\n> >\n> > > +\n> > >       git reset --hard HEAD^ &&\n> > >       git checkout change &&\n> > > +\n> > > +     test-tool chmtime =-1 M &&\n> > > +     test-tool chmtime --get M >old-mtime &&\n> >\n> > Here, however, you compare the mtime of 'M' before the merge ...\n> >\n> > >       GIT_MERGE_VERBOSITY=3 git merge change+rename >out &&\n> > > -     test_i18ngrep ! \"^Skipped B\" out\n> > > +\n> > > +     test-tool chmtime --get B >new-mtime &&\n> > > +     test $(cat old-mtime) -lt $(cat new-mtime)\n> >\n> > ... with the mtime of 'B' after the merge, i.e. the mtimes of two\n> > different files.\n> >\n> > Is that right?\n> \n> No, sounds like a copy-and-paste-and-forget-to-update bug.  Thanks for\n> spotting it.  Since you found it, do you want to submit a patch with\n> the fix?\n\nNo :)  There is no file 'B' in branch 'change', so I think the fix\nrequires your expertise to make sure that the test checks what it was\nsupposed to check.\n\n"},{"id":"393217","messageId":"CABPp-BH-J6UehBgW9K9Q+3sfhAZYMkE3nabdC8hTkidHjiZH8Q@mail.gmail.com","threadId":"52895","inReplyTo":"20200313171739.GF3122@szeder.dev","subject":"Re: [PATCH 4/5] t6022, t6046: test expected behavior instead of testing a proxy for it","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-03-13T17:45:50Z","receivedAt":"2020-03-13T17:46:06Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Fri, Mar 13, 2020 at 10:17 AM SZEDER Gábor <szeder.dev@gmail.com> wrote:\n>\n> On Thu, Mar 12, 2020 at 09:01:57PM +0100, SZEDER Gábor wrote:\n> > > > > I saw this test fail today in one of my custom CI builds:\n> > > > >\n> > > > >   +git checkout change\n> > > > >   Switched to branch 'change'\n> > > > >   +test-tool chmtime =-1 M\n> > > > >   +test-tool chmtime --get M\n> > > > >   +GIT_MERGE_VERBOSITY=3 git merge change+rename\n> > > > >   +test-tool chmtime --get B\n> > > > >   +cat old-mtime\n> > > > >   +cat new-mtime\n> > > > >   +test 1583967731 -lt 1583967731\n> > > > >   error: last command exited with $?=1\n> > > > >   not ok 12 - merge of identical changes in a renamed file\n> > > > >\n> > > > > The contents of 'out', i.e. the output of the 'git merge' command\n> > > > > before the failure is:\n> > > > >\n> > > > >   Auto-merging B\n> > > > >   Merge made by the 'recursive' strategy.\n> > > > >    A => B | 0\n> > > > >    1 file changed, 0 insertions(+), 0 deletions(-)\n> > > > >    rename A => B (100%)\n> > > > >\n> > > > > This is a rare failure, this is the first time I saw it, and to make\n> > > > > things worse, this one time it happened on big-endian and with all the\n> > > > > GIT_TEST_* knobs enabled.\n> > > > >\n> > > > >   https://travis-ci.org/github/szeder/git-cooking-topics-for-travis-ci/jobs/661294571#L4020\n> > > >\n> > > > This is very troubling.  The workflow is basically:\n> > > >   - Manually set the mtime to a file to something old (I happened to\n> > > > pick 1 second before now, but picking something from 1970 would have\n> > > > been fine too).\n> > > >   - Run a merge which is known to need to overwrite the file.  Your\n> > > > output (\"Auto-merging B\") suggests that we should have been in such a\n> > > > case.\n> > > >   - Verify that the file was actually updated as expected.  Since the\n> > > > OS is supposed to update the mtime when it writes the file, it should\n> > > > have set it to something recent, i.e. something *different* than what\n> > > > it had before.\n> > > >\n> > > > So, now I'm left wondering how the mtime possibly could have been not\n> > > > updated.  Maybe the file wasn't actually written?  (But if so, why\n> > > > didn't other people see the failure?  Or your stress runs not see it?)\n> > > >  Or maybe it was written but all file contents and metadata were\n> > > > delayed in writing to disk such that a subsequent command still sees\n> > > > the old file??  Or maybe it was written but the mtime update was\n> > > > delayed and the test was able to check it in that intermediate\n> > > > state???  Or perhaps the mtime check before the merge raced with the\n> > > > setting of the mtime backwards and got the mtime before it was\n> > > > rewound????\n> > > >\n> > > > I don't have a plausible scenario under which any of these should be\n> > > > possible; I'm at a loss.\n> > >\n> > > Hmm.  Maybe leap seconds, or clock updates via ntp at an unfortunate\n> > > time?\n> >\n> > I'm now fairly confident that 'git merge' is OK, and suspect that it's\n> > an issue with Travis CI's s390x environment (multi-architecture\n> > support is an alpha-stage feature).\n>\n> I could finally reproduce the issue on my own machine, so apparently\n> it's not an issue in Travis CI's multi-arch environments.\n>\n> >   test_expect_success 'test' '\n> >       touch file &&\n> >       old=$(test-tool chmtime --get =-1 file) &&\n> >       touch file &&\n> >       new=$(test-tool chmtime --get file) &&\n> >       test $old -lt $new\n> >   '\n>\n> I wanted to report the issue to Travis CI, and in order to do so I\n> turned the above test case into a script that doesn't at all depend on\n> out test framework and 'test-tool' but uses only coreutils commands\n> (with a whole lot of GNUisms...):\n>\n>   cat >timestamp.sh <<-\\EOF\n>   #!/bin/sh\n>\n>   set -ex\n>\n>   i=0\n>   while true\n>   do\n>         printf \"$i\\r\"\n>         i=$((i + 1))\n>\n>         # set a file's mtime to one second ago\n>         now=$(date \"+%s.%N\")\n>         one_sec_ago=$(date -d \"@$((${now%.*} - 1))\" \"+%Y%m%d%H%M%S\")\n>         touch -t ${one_sec_ago%??}.${one_sec_ago#????????????} file\n>         # save its actual mtime\n>         old=$(date -r file \"+%s.%N\")\n>         # set its mtime to now\n>         touch file\n>         # the current the mtime should be different, but sometimes it isn't\n>         new=$(date -r file \"+%s.%N\")\n>         test \"${old%.*}\" != \"${new%.*}\"\n>   done\n>   EOF\n>   chmod u+x timestamp.sh\n>   ./timestamp.sh 2>out\n>   echo\n>   tail -n11 out\n>\n> And this script usually fails after a few hundred iterations on my\n> machine:\n>\n>   308\n>   + date +%s.%N\n>   + now=1584118408.002458987\n>   + date -d @1584118407 +%Y%m%d%H%M%S\n>   + one_sec_ago=20200313175327\n>   + touch -t 202003131753.27 file\n>   + date -r file +%s.%N\n>   + old=1584118407.000000000\n>   + touch file\n>   + date -r file +%s.%N\n>   + new=1584118407.997464837\n>   + test 1584118407 != 1584118407\n>\n> Note that the mtime update at the end of the iteration results in an\n> mtime that is _before_ the current time at the beginning of the\n> iteration.  Well, I'm puzzled :)\n\nInteresting...\n\nFrom https://stackoverflow.com/questions/14392975/timestamp-accuracy-on-ext4-sub-millsecond:\n'''\ndate will call the gettimeofday system call which will always return\nthe most accurate time available based on the cached kernel time,\nadjusted by the CPU cycle time if available to give nanosecond\nresolution. The timestamps stored in the file system however, are only\nbased on the cached kernel time. ie The time calculated at the last\ntimer interrupt.\n'''\n\nalso, from https://apenwarr.ca/log/20181113 says:\n\n'''\nDoes mtime get set to >= the current time?\n\nNo, this depends on clock granularity. For example, gettimeofday() can\nreturn times in microseconds on my system, but ext4 rounds timestamps\ndown to the previous ~10ms (but not exactly 10ms) increment, with the\nsurprising result that a newly-created file is almost always created\nin the past:\n\n  $ python -c \"\n  import os, time\n  t0 = time.time()\n  open('testfile', 'w').close()\n  print os.stat('testfile').st_mtime - t0\n  \"\n\n  -0.00234484672546\n'''\n\n\nSo, perhaps instead of setting the file mtime relative to the current\nclock (and truncated to the nearest integer), we need to set the file\nmtime relative to its recorded mtime.\n\n> Yes, setting the old timestamp 2 seconds in the past seems to be\n> sufficient, at least I haven't seen it fail in a few 100k repetitions.\n\nOr yeah, we could just use bigger numbers, but given that wall clock\nand file-system clock are apparently different, I like the idea of\nsetting them relative to the mtimes that existed before.  Looks like\n`test-tool chmtime` supports that too, so I'll cook up a patch.\n"},{"id":"393222","messageId":"CABPp-BH71UVqf8X8Syx5PfhE+-htrwd8aCW87NzR9Kubxp9-xA@mail.gmail.com","threadId":"52895","inReplyTo":"CABPp-BGt4xaqG+3m3q=PfMTmfotjvze2TPp5JhthE2YHsLa=-Q@mail.gmail.com","subject":"Re: [PATCH 4/5] t6022, t6046: test expected behavior instead of testing a proxy for it","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-03-13T18:11:20Z","receivedAt":"2020-03-13T18:11:37Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Fri, Mar 13, 2020 at 10:18 AM Elijah Newren <newren@gmail.com> wrote:\n>\n> On Fri, Mar 13, 2020 at 10:12 AM SZEDER Gábor <szeder.dev@gmail.com> wrote:\n> >\n> > On Thu, Feb 27, 2020 at 12:14:23AM +0000, Elijah Newren via GitGitGadget wrote:\n> > > diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh\n> > > index 6f196aaf276..d97cf48495b 100755\n> > > --- a/t/t6022-merge-rename.sh\n> > > +++ b/t/t6022-merge-rename.sh\n> > > @@ -242,12 +242,23 @@ test_expect_success 'merge of identical changes in a renamed file' '\n> > >       rm -f A M N &&\n> > >       git reset --hard &&\n> > >       git checkout change+rename &&\n> > > +\n> > > +     test-tool chmtime =31337 B &&\n> > > +     test-tool chmtime --get B >old-mtime &&\n> >\n> > Here you compare the mtime of 'B' before ...\n> >\n> > >       GIT_MERGE_VERBOSITY=3 git merge change >out &&\n> > > -     test_i18ngrep \"^Skipped B\" out &&\n> > > +\n> > > +     test-tool chmtime --get B >new-mtime &&\n> > > +     test_cmp old-mtime new-mtime &&\n> >\n> > ... and after the merge.\n> >\n> > > +\n> > >       git reset --hard HEAD^ &&\n> > >       git checkout change &&\n> > > +\n> > > +     test-tool chmtime =-1 M &&\n> > > +     test-tool chmtime --get M >old-mtime &&\n> >\n> > Here, however, you compare the mtime of 'M' before the merge ...\n> >\n> > >       GIT_MERGE_VERBOSITY=3 git merge change+rename >out &&\n> > > -     test_i18ngrep ! \"^Skipped B\" out\n> > > +\n> > > +     test-tool chmtime --get B >new-mtime &&\n> > > +     test $(cat old-mtime) -lt $(cat new-mtime)\n> >\n> > ... with the mtime of 'B' after the merge, i.e. the mtimes of two\n> > different files.\n> >\n> > Is that right?\n>\n> No, sounds like a copy-and-paste-and-forget-to-update bug.  Thanks for\n> spotting it.  Since you found it, do you want to submit a patch with\n> the fix?\n\nActually, it wasn't wrong.  Definitely needs some comments explaining\nthe weird construct, though.\n"}]}