{"thread":{"id":"23562","subject":"[PATCH v2] Make git log --follow find copies among unmodified files.","startedAt":"2010-04-22T03:50:44Z","lastAt":"2010-04-22T06:26:57Z","messageCount":2,"participants":["Bo Yang","Junio C Hamano"],"isPatch":true,"patchVersion":2,"patchTotal":null},"messages":[{"id":"140100","messageId":"1271908244-18910-1-git-send-email-struggleyb.nku@gmail.com","threadId":"23562","inReplyTo":null,"subject":"[PATCH v2] Make git log --follow find copies among unmodified files.","fromName":"Bo Yang","fromEmail":"struggleyb.nku@gmail.com","sentAt":"2010-04-22T03:50:44Z","receivedAt":"2010-04-22T03:50:44Z","isPatch":true,"sender":{"key":"struggleyb.nku@gmail.com","avatar":"https://avatars.githubusercontent.com/u/233030?v=4"},"body":"'git log --follow <path>' don't track copies from unmodified\nfiles, and this patch fix it.\n\nSigned-off-by: Bo Yang <struggleyb.nku@gmail.com>\n---\n Documentation/git-log.txt           |    5 ++-\n diff.c                              |    3 ++\n t/t4205-log-follow-harder-copies.sh |   56 +++++++++++++++++++++++++++++++++++\n tree-diff.c                         |    2 +\n 4 files changed, 65 insertions(+), 1 deletions(-)\n create mode 100755 t/t4205-log-follow-harder-copies.sh\n\ndiff --git a/Documentation/git-log.txt b/Documentation/git-log.txt\nindex fb184ba..682a85a 100644\n--- a/Documentation/git-log.txt\n+++ b/Documentation/git-log.txt\n@@ -56,7 +56,10 @@ include::diff-options.txt[]\n \tcommits, and doesn't limit diff for those commits.\n \n --follow::\n-\tContinue listing the history of a file beyond renames.\n+\tContinue listing the history of a file beyond renames/copies.\n+\tWith this, all files in a commit will be searched for\n+\trenames/copies, and it is equal to specify '--follow' with\n+\t'--follow -M -C -C'.\n \n --log-size::\n \tBefore the log message print out its size in bytes. Intended\ndiff --git a/diff.c b/diff.c\nindex d0ecbc3..6982f79 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -2594,6 +2594,9 @@ int diff_setup_done(struct diff_options *options)\n \telse\n \t\tDIFF_OPT_CLR(options, DIFF_FROM_CONTENTS);\n \n+\tif (DIFF_OPT_TST(options, FOLLOW_RENAMES))\n+\t\tDIFF_OPT_SET(options, FIND_COPIES_HARDER);\n+\n \tif (DIFF_OPT_TST(options, FIND_COPIES_HARDER))\n \t\toptions->detect_rename = DIFF_DETECT_COPY;\n \ndiff --git a/t/t4205-log-follow-harder-copies.sh b/t/t4205-log-follow-harder-copies.sh\nnew file mode 100755\nindex 0000000..ad29e65\n--- /dev/null\n+++ b/t/t4205-log-follow-harder-copies.sh\n@@ -0,0 +1,56 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2010 Bo Yang\n+#\n+\n+test_description='Test --follow should always find copies hard in git log.\n+\n+'\n+. ./test-lib.sh\n+. \"$TEST_DIRECTORY\"/diff-lib.sh\n+\n+echo >path0 'Line 1\n+Line 2\n+Line 3\n+'\n+\n+test_expect_success \\\n+    'add a file path0 and commit.' \\\n+    'git add path0 &&\n+     git commit -m \"Add path0\"'\n+\n+echo >path0 'New line 1\n+New line 2\n+New line 3\n+'\n+test_expect_success \\\n+    'Change path0.' \\\n+    'git add path0 &&\n+     git commit -m \"Change path0\"'\n+\n+cat <path0 >path1\n+test_expect_success \\\n+    'copy path0 to path1.' \\\n+    'git add path1 &&\n+     git commit -m \"Copy path1 from path0\"'\n+\n+test_expect_success \\\n+    'find the copy path0 -> path1 harder' \\\n+    'git log --follow --name-status --pretty=\"format:%s\"  path1 > current'\n+\n+cat >expected <<\\EOF\n+Copy path1 from path0\n+C100\tpath0\tpath1\n+\n+Change path0\n+M\tpath0\n+\n+Add path0\n+A\tpath0\n+EOF\n+\n+test_expect_success \\\n+    'validate the output.' \\\n+    'compare_diff_patch current expected'\n+\n+test_done\ndiff --git a/tree-diff.c b/tree-diff.c\nindex fe9f52c..0dea53e 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -346,6 +346,8 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co\n \n \tdiff_setup(&diff_opts);\n \tDIFF_OPT_SET(&diff_opts, RECURSIVE);\n+\tif (DIFF_OPT_TST(opt, FIND_COPIES_HARDER))\n+\t\tDIFF_OPT_SET(&diff_opts, FIND_COPIES_HARDER);\n \tdiff_opts.detect_rename = DIFF_DETECT_RENAME;\n \tdiff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;\n \tdiff_opts.single_follow = opt->paths[0];\n-- \n1.7.0.2.273.gc2413.dirty\n"},{"id":"140103","messageId":"7v1ve86lzi.fsf@alter.siamese.dyndns.org","threadId":"23562","inReplyTo":"1271908244-18910-1-git-send-email-struggleyb.nku@gmail.com","subject":"Re: [PATCH v2] Make git log --follow find copies among unmodified files.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-04-22T06:26:57Z","receivedAt":"2010-04-22T06:26:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Bo Yang <struggleyb.nku@gmail.com> writes:\n\n> @@ -56,7 +56,10 @@ include::diff-options.txt[]\n>  \tcommits, and doesn't limit diff for those commits.\n>  \n>  --follow::\n> -\tContinue listing the history of a file beyond renames.\n> +\tContinue listing the history of a file beyond renames/copies.\n> +\tWith this, all files in a commit will be searched for\n> +\trenames/copies, and it is equal to specify '--follow' with\n> +\t'--follow -M -C -C'.\n\nHmm.\n\nAddition of \"/copies\" is fine, but I do not think the last three lines are\ngood.  The -M/-C options are about how the changes introduced by the found\ncommits are shown, and because the pathspec limitation applies _before_\nall the diffcore transformations (see \"Gaah. Why?\" message from Linus in\nthe thread I pointed at you in another message), and because the --follow\noption is defined to work _only_ when you give one single path (it is not\neven a \"pathspec\" in the usual sense; see 750f7b6 (Finally implement \"git\nlog --follow\", 2007-06-19)), they are inherently mutually incompatible.\n\nCf. http://thread.gmane.org/gmane.comp.version-control.git/50512/focus=50513\n\n> diff --git a/diff.c b/diff.c\n> index d0ecbc3..6982f79 100644\n> --- a/diff.c\n> +++ b/diff.c\n> @@ -2594,6 +2594,9 @@ int diff_setup_done(struct diff_options *options)\n>  \telse\n>  \t\tDIFF_OPT_CLR(options, DIFF_FROM_CONTENTS);\n>  \n> +\tif (DIFF_OPT_TST(options, FOLLOW_RENAMES))\n> +\t\tDIFF_OPT_SET(options, FIND_COPIES_HARDER);\n\nI don't think this is correct.  You are touching the diff options on the\n\"how do we show the found change\" side here.\n\nBecause the user is fixated on one single path F, it is enough to say \"F\nis in the child but did not exist in the parent---it appears to have come\nfrom E in the parent\" without saying if it is copy or rename.  I think it\nis Ok if the change is to pay the cost of full tree scanning for only\ncommits that try_to_follow_renames() deals with, but this instead makes it\nin effect for _all_ the commits, not just the ones that created the path\nthat has been followed so far, which is unacceptable.\n\nWhy isn't it just a one-liner from your previous patch but done without\nthe conditional?  I think that would indeed be a fix.  With \"--follow\",\nthe user expressee that it is Ok to pay extra cost in order to _follow_\nthat single path, and we haven't been doing as thorough a job as we could.\nWith that single liner, you are fixing it to pay more attention to the\npaths in the parent.\n\nBut that is _not_ about how the found commits are _shown_ (it is about how\nthe commits are _found_).\n\ndiff --git a/tree-diff.c b/tree-diff.c\nindex fe9f52c..0dea53e 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -346,6 +346,7 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co\n \n \tdiff_setup(&diff_opts);\n \tDIFF_OPT_SET(&diff_opts, RECURSIVE);\n+\tDIFF_OPT_SET(&diff_opts, FIND_COPIES_HARDER);\n \tdiff_opts.detect_rename = DIFF_DETECT_RENAME;\n \tdiff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;\n \tdiff_opts.single_follow = opt->paths[0];\n-- \n1.7.0.2.273.gc2413.dirty\n"}]}