{"thread":{"id":"37794","subject":"[PATCH] diff -B -M: fix output for \"copy and then rewrite\" case","startedAt":"2014-10-23T23:34:40Z","lastAt":"2014-10-23T23:34:40Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"251004","messageId":"xmqqoat2gy27.fsf@gitster.dls.corp.google.com","threadId":"37794","inReplyTo":null,"subject":"[PATCH] diff -B -M: fix output for \"copy and then rewrite\" case","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-10-23T23:34:40Z","receivedAt":"2014-10-23T23:34:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Starting from a single file, A, if you create B as a copy of A (and\npossibly make some edit) and then make extensive change to A, you\nwill see:\n\n    $ git diff -C --name-status\n    C89    A    B\n    M      A\n\nwhich is expected.  However, if you ask the same question in a\ndifferent way, you see this:\n\n    $ git diff -B -M --name-status\n    R89    A    B\n    M100   A\n\ntelling us that A was rename-edited into B (as if \"A will no longer\nexist as the result\") and at the same time A itself was extensively\nedited.\n\nIn this case, because the resulting tree still does have file A\n(even if it has contents vastly different from the original), we\nshould use \"C\"opy, not \"R\"ename, to avoid hinting that A somehow\ngoes away.\n\nTwo existing tests were depending on the wrong behaviour, and fixed.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n diffcore-break.c                  | 7 +++++++\n t/t4008-diff-break-rewrite.sh     | 4 ++--\n t/t4023-diff-rename-typechange.sh | 3 ++-\n 3 files changed, 11 insertions(+), 3 deletions(-)\n\ndiff --git a/diffcore-break.c b/diffcore-break.c\nindex 1d9e530..5473493 100644\n--- a/diffcore-break.c\n+++ b/diffcore-break.c\n@@ -246,6 +246,13 @@ static void merge_broken(struct diff_filepair *p,\n \n \tdp = diff_queue(outq, d->one, c->two);\n \tdp->score = p->score;\n+\t/*\n+\t * We will be one extra user of the same src side of the\n+\t * broken pair, if it was used as the rename source for other\n+\t * paths elsewhere.  Increment to mark that the path stays\n+\t * in the resulting tree.\n+\t */\n+\td->one->rename_used++;\n \tdiff_free_filespec_data(d->two);\n \tdiff_free_filespec_data(c->one);\n \tfree(d);\ndiff --git a/t/t4008-diff-break-rewrite.sh b/t/t4008-diff-break-rewrite.sh\nindex 27e98a8..8920464 100755\n--- a/t/t4008-diff-break-rewrite.sh\n+++ b/t/t4008-diff-break-rewrite.sh\n@@ -123,10 +123,10 @@ test_expect_success \\\n     'git diff-index -B -M \"$tree\" >current'\n \n # file0 changed from regular to symlink.  file1 is very close to the preimage of file0.\n-# because we break file0, file1 can become a rename of it.\n+# the change does not make file0 disappear, so file1 is denoted as a copy of file0\n cat >expected <<\\EOF\n :100644 120000 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 67be421f88824578857624f7b3dc75e99a8a1481 T\tfile0\n-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 R\tfile0\tfile1\n+:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 C\tfile0\tfile1\n EOF\n \n test_expect_success \\\ndiff --git a/t/t4023-diff-rename-typechange.sh b/t/t4023-diff-rename-typechange.sh\nindex 55d549f..8c98237 100755\n--- a/t/t4023-diff-rename-typechange.sh\n+++ b/t/t4023-diff-rename-typechange.sh\n@@ -76,7 +76,8 @@ test_expect_success 'moves and renames' '\n \n \tgit diff-tree three four -r --name-status -B -M | sort >actual &&\n \t{\n-\t\techo \"R100\tfoo\tbar\"\n+\t\t# see -B -M (#6) in t4008\n+\t\techo \"C100\tfoo\tbar\"\n \t\techo \"T100\tfoo\"\n \t} | sort >expect &&\n \ttest_cmp expect actual\n-- \n2.1.2-595-g1568c45\n"}]}