{"thread":{"id":"23382","subject":"[PATCH 0/2] Document update for 'git-blame' '-M' and '-C' option","startedAt":"2010-04-08T06:51:28Z","lastAt":"2010-04-09T05:11:55Z","messageCount":7,"participants":["Bo Yang","Junio C Hamano","Thomas Rast"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"138937","messageId":"1270709490-19163-1-git-send-email-struggleyb.nku@gmail.com","threadId":"23382","inReplyTo":null,"subject":"[PATCH 0/2] Document update for 'git-blame' '-M' and '-C' option","fromName":"Bo Yang","fromEmail":"struggleyb.nku@gmail.com","sentAt":"2010-04-08T06:51:28Z","receivedAt":"2010-04-08T06:51:28Z","isPatch":true,"sender":{"key":"struggleyb.nku@gmail.com","avatar":"https://avatars.githubusercontent.com/u/233030?v=4"},"body":"The current 'git-blame' manual state that '-M' detect code move and '-C' detect code copy. After read some code of 'git-blame' and some expriments with it. I found that both '-M' and '-C' detect code move and copy. So, I think the document should be updated.\nThanks Thomas Rast a lot for his help on this patch.\n\nBo Yang (2):\n  Add a basic idea section for git-blame.\n  Change the description of '-M' and '-C' option.\n\n Documentation/blame-options.txt |   41 +++++++++++++++++++++++---------------\n Documentation/git-blame.txt     |   32 ++++++++++++++++++++++++++++++\n 2 files changed, 57 insertions(+), 16 deletions(-)\n"},{"id":"138938","messageId":"1270709490-19163-2-git-send-email-struggleyb.nku@gmail.com","threadId":"23382","inReplyTo":"1270709490-19163-1-git-send-email-struggleyb.nku@gmail.com","subject":"[PATCH 1/2] Add a basic idea section for git-blame.","fromName":"Bo Yang","fromEmail":"struggleyb.nku@gmail.com","sentAt":"2010-04-08T06:51:29Z","receivedAt":"2010-04-08T06:51:29Z","isPatch":true,"sender":{"key":"struggleyb.nku@gmail.com","avatar":"https://avatars.githubusercontent.com/u/233030?v=4"},"body":"Explain the basic idea about blame shifting with\n'-M' or '-C' given.\n\nSigned-off-by: Thomas Rast <trast@student.ethz.ch>\nSigned-off-by: Bo Yang <struggleyb.nku@gmail.com>\n---\n Documentation/git-blame.txt |   32 ++++++++++++++++++++++++++++++++\n 1 files changed, 32 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt\nindex a27f439..e31b87f 100644\n--- a/Documentation/git-blame.txt\n+++ b/Documentation/git-blame.txt\n@@ -36,6 +36,38 @@ $ git log --pretty=oneline -S'blame_usage'\n ea4c7f9bf69e781dd0cd88d2bccb2bf5cc15c9a7 git-blame: Make the output\n -----------------------------------------------------------------------------\n \n+\n+BASIC IDEA\n+----------\n+\n+This section briefly explains the basic idea behind 'git-blame'.  You\n+do not have to understand it to use git-blame, but it helps in\n+understanding the `-M` and `-C` options.  For the sake of simplicity,\n+we assume that history is linear.\n+\n+A call to `git-blame <rev> -- <file>` works as follows:\n+\n+- Look at `git diff <rev>^ <rev>` to see what the commit did.\n+\n+- Discard all `-` lines in the diff, since they are no longer part of\n+  `<file>`.\n+\n+- Take blame for all `+` lines; i.e., the newly added lines according\n+  to the diff are attributed to `<rev>`.\n+\n+- Shift blame for all unchanged lines to the parent; i.e., these lines\n+  are attributed as in a call to `git blame <rev>^ -- <file>`.\n+\n+Note that this does not expend any effort to shift blame of `+`\n+lines.  This can be changed with the `-M` and `-C` options.\n+\n+With `-M`, this command detects same lines of the current blaming code\n+inside the current file. And it will shift the blame to the author of\n+the original lines instead of author of current blaming code. It does\n+the same for `-C` except that it will search across file boundary and\n+multiple commits.\n+\n+\n OPTIONS\n -------\n include::blame-options.txt[]\n-- \n1.6.0.4\n"},{"id":"138939","messageId":"1270709490-19163-3-git-send-email-struggleyb.nku@gmail.com","threadId":"23382","inReplyTo":"1270709490-19163-2-git-send-email-struggleyb.nku@gmail.com","subject":"[PATCH 2/2] Change the description of '-M' and '-C' option.","fromName":"Bo Yang","fromEmail":"struggleyb.nku@gmail.com","sentAt":"2010-04-08T06:51:30Z","receivedAt":"2010-04-08T06:51:30Z","isPatch":true,"sender":{"key":"struggleyb.nku@gmail.com","avatar":"https://avatars.githubusercontent.com/u/233030?v=4"},"body":"Both '-M' and '-C' option detect code moving and copying.\nThe difference between the two options is whether they\nsearch across file boundary.\n\nSigned-off-by: Thomas Rast <trast@student.ethz.ch>\nSigned-off-by: Bo Yang <struggleyb.nku@gmail.com>\n---\n Documentation/blame-options.txt |   41 +++++++++++++++++++++++---------------\n 1 files changed, 25 insertions(+), 16 deletions(-)\n\ndiff --git a/Documentation/blame-options.txt b/Documentation/blame-options.txt\nindex 4833cac..aca2a1c 100644\n--- a/Documentation/blame-options.txt\n+++ b/Documentation/blame-options.txt\n@@ -79,14 +79,15 @@ of lines before or after the line given by <start>.\n \tof the --date option at linkgit:git-log[1].\n \n -M|<num>|::\n-\tDetect moving lines in the file as well.  When a commit\n-\tmoves a block of lines in a file (e.g. the original file\n-\thas A and then B, and the commit changes it to B and\n-\tthen A), the traditional 'blame' algorithm typically blames\n-\tthe lines that were moved up (i.e. B) to the parent and\n-\tassigns blame to the lines that were moved down (i.e. A)\n-\tto the child commit.  With this option, both groups of lines\n-\tare blamed on the parent.\n+\tDetect moving/copying lines in the file as well.  Instead of\n+\ttaking blame for all added lines, attempt to find the same\n+\tlines 'in the same file' in the parent commit.  If such a\n+\tmatch was found, shift the blame to these lines in the\n+\tparent. (This expends extra effort on the order of the size\n+\tof the file for every change.)\n++\n+The net effect is that if code is moved or copied within the file, the\n+lines are attributed to the original instead of the move/copy.\n +\n <num> is optional but it is the lower bound on the number of\n alphanumeric characters that git must detect as moving\n@@ -94,14 +95,22 @@ within a file for it to associate those lines with the parent\n commit.\n \n -C|<num>|::\n-\tIn addition to `-M`, detect lines copied from other\n-\tfiles that were modified in the same commit.  This is\n-\tuseful when you reorganize your program and move code\n-\taround across files.  When this option is given twice,\n-\tthe command additionally looks for copies from other\n-\tfiles in the commit that creates the file. When this\n-\toption is given three times, the command additionally\n-\tlooks for copies from other files in any commit.\n+\tLike `-M`, detect moving/copying lines between files as well.\n+\tInstead of taking blame for all added lines, attempt to find the same\n+\tlines across file boundary according to the number of given `-C`.\n+\tThis is useful when you reorganize your program and move/copy\n+\tcode around across files. When this option is given once, detect\n+\tlines moved/copied from other files that were modified in the\n+\tsame commit. (This expends extra effort on the order of\n+\t<number of modified files>*<file size> for every change.) When this\n+\toption is given twice, the command additionally looks for moves/copies\n+\tfrom other files in the commit that creates this file. (This expends\n+\textra effort on the order of <number of files in the commit>*<file size>\n+\tfor every change.) When this option is given three times, the\n+\tcommand additionally looks for moves/copies from other files\n+\tin any commit. (This expends extra effort on the order of\n+\t<commit number>*<number of files in one commit>*<file size>\n+\tfor every change.)\n +\n <num> is optional but it is the lower bound on the number of\n alphanumeric characters that git must detect as moving\n-- \n1.6.0.4\n"},{"id":"138950","messageId":"7vmxxe74s2.fsf@alter.siamese.dyndns.org","threadId":"23382","inReplyTo":"1270709490-19163-2-git-send-email-struggleyb.nku@gmail.com","subject":"Re: [PATCH 1/2] Add a basic idea section for git-blame.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-04-08T08:00:13Z","receivedAt":"2010-04-08T08:00:13Z","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> +A call to `git-blame <rev> -- <file>` works as follows:\n> +\n> +- Look at `git diff <rev>^ <rev>` to see what the commit did.\n> +\n> +- Discard all `-` lines in the diff, since they are no longer part of\n> +  `<file>`.\n> +\n> +- Take blame for all `+` lines; i.e., the newly added lines according\n> +  to the diff are attributed to `<rev>`.\n\nI hate to say it, but this is horrifying; it works quite the other way\naround.\n\nThe name of the game is not \"take blame by looking at the diff to see what\nwe introduced\"; it is \"avoid taking blame at all cost, by looking at the\ndiff to see what we might have inherited from our parents\".\n\nA description closer to the truth would be:\n\n - Look at output of \"git diff <rev>^$n <rev>\" for each parent ($n runs\n   from 1 to number of parents);\n\n - Ignore all +/- lines.  The context ' ' lines and lines outside of diff\n   hunks are known to have been inherited from $n-th parent and they are\n   not our fault.  We can happily pass blame for these lines to our\n   parent.\n\n - Do the above for all the parents.  We (grudgingly) take blame for lines\n   that we failed to find corresponding lines in our parents.\n\nThe -M option affects what happens between the second and the third step.\nWe try to see if the lines that we did not pass blame to <rev>^$n might\nhave come from <rev>^$n by running diff between the remainder and the blob\nin <rev>^$n *again*.  This lets us catch code movement within the blob,\nhence the name of the option -M.\n\nThe -C option affects the choice of the blob in <rev>^$n.  Usually, we\ninternally run an equivalent of \"git diff -M <rev>^$n <rev>\" to notice\nthat the file F that we are analyzing used to be called F' in $n-th\nparent, and run the diff against it, but -C allows us to check with paths\nother than that, and additional -C enlarges the search space.  This is to\nnotice code movement (with a single -C) or copies (with more -Cs) across\npaths.\n\nFor illustrated description, read the classic:\n \n    http://thread.gmane.org/gmane.comp.version-control.git/28826\n\nAlmost all the hits in the first page from this query would help, too:\n\nhttp://search.gmane.org/?query=On+blame%2Fpickaxe&author=Junio+C+Hamano&group=gmane.comp.version-control.git&sort=revdate&DEFAULTOP=and&[=2&xP=blame%09pickaxe&xFILTERS=Gcomp.version-control.git-Ac-Ahamano-Ajunio---A\n"},{"id":"138966","messageId":"201004081827.22706.trast@student.ethz.ch","threadId":"23382","inReplyTo":"7vmxxe74s2.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 1/2] Add a basic idea section for git-blame.","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2010-04-08T16:27:22Z","receivedAt":"2010-04-08T16:27:22Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Junio C Hamano wrote:\n> Bo Yang <struggleyb.nku@gmail.com> writes:\n> \n> > +A call to `git-blame <rev> -- <file>` works as follows:\n> > +\n> > +- Look at `git diff <rev>^ <rev>` to see what the commit did.\n> > +\n> > +- Discard all `-` lines in the diff, since they are no longer part of\n> > +  `<file>`.\n> > +\n> > +- Take blame for all `+` lines; i.e., the newly added lines according\n> > +  to the diff are attributed to `<rev>`.\n> \n> I hate to say it, but this is horrifying; it works quite the other way\n> around.\n> \n> The name of the game is not \"take blame by looking at the diff to see what\n> we introduced\"; it is \"avoid taking blame at all cost, by looking at the\n> diff to see what we might have inherited from our parents\".\n\n\"Horrifying\" seems a fairly harsh word for another way to describe the\nprocess *in linear history* and with default settings, doesn't it?\n\nI now see that \"assume linear history\" is oversimplifying the process,\nbut I have to take blame^W^W^W^Wwill fail to shift blame for it since\nI suggested that.\n\n> For illustrated description, read the classic:\n>  \n>     http://thread.gmane.org/gmane.comp.version-control.git/28826\n> \n> Almost all the hits in the first page from this query would help, too:\n> \n> http://search.gmane.org/?query=On+blame%2Fpickaxe&author=Junio+C+Hamano&group=gmane.comp.version-control.git&sort=revdate&DEFAULTOP=and&[=2&xP=blame%09pickaxe&xFILTERS=Gcomp.version-control.git-Ac-Ahamano-Ajunio---A\n\nThanks.  I trust this will help Bo make a revised description for the\nmanpage.\n\n\n\n[PS for the list record: while part of the patches is indeed mine, I\nnever signed off on them.]\n\n-- \nThomas Rast\ntrast@{inf,student}.ethz.ch\n"},{"id":"138967","messageId":"7v8w8x7ura.fsf@alter.siamese.dyndns.org","threadId":"23382","inReplyTo":"201004081827.22706.trast@student.ethz.ch","subject":"Re: [PATCH 1/2] Add a basic idea section for git-blame.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-04-08T16:51:21Z","receivedAt":"2010-04-08T16:51:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Rast <trast@student.ethz.ch> writes:\n\n> \"Horrifying\" seems a fairly harsh word for another way to describe the\n> process *in linear history* and with default settings, doesn't it?\n\nNo, even in a linear setting, if you start from \"We discard \"-\" and take\nblame for +\", you can never get to -M/-C.\n\nSuppose you had \"a/b/c/\" in the parent and \"1/b/c/2/a/3/4/a/5/\" in the\nchild (\"/\" stands for LF).  Your \"b/c/\" would match and you say \"I added\n1/, 2/a/3/4/a/5/\".  How would you fix that so that you can say that \"a/\"\nafter \"2/\" was actually moved from the first line, and possibly the second\n\"a/\" was also copied from the same line, if you discard all \"-\"?\n\nYou can say \"in linear history and no -M nor -C, you could annotate things\nthis way\", but then you are not describing \"blame\" anymore; you are\ndescribing something else that may work very well in much simpler setting\nand it might even be how some other SCMs would do it.\n\nBut it _is_ horrifying to see that in a section that begins with \"blame\nworks as follows\".\n"},{"id":"139008","messageId":"x2z41f08ee11004082211g6ae76f38ic1ee65e508b16343@mail.gmail.com","threadId":"23382","inReplyTo":"7vmxxe74s2.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 1/2] Add a basic idea section for git-blame.","fromName":"Bo Yang","fromEmail":"struggleyb.nku@gmail.com","sentAt":"2010-04-09T05:11:55Z","receivedAt":"2010-04-09T05:11:55Z","isPatch":true,"sender":{"key":"struggleyb.nku@gmail.com","avatar":"https://avatars.githubusercontent.com/u/233030?v=4"},"body":"Hi Junio,\nOn Thu, Apr 8, 2010 at 1:00 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> The name of the game is not \"take blame by looking at the diff to see what\n> we introduced\"; it is \"avoid taking blame at all cost, by looking at the\n> diff to see what we might have inherited from our parents\".\n>\n> A description closer to the truth would be:\n>\n>  - Look at output of \"git diff <rev>^$n <rev>\" for each parent ($n runs\n>   from 1 to number of parents);\n>\n>  - Ignore all +/- lines.  The context ' ' lines and lines outside of diff\n>   hunks are known to have been inherited from $n-th parent and they are\n>   not our fault.  We can happily pass blame for these lines to our\n>   parent.\n>\n>  - Do the above for all the parents.  We (grudgingly) take blame for lines\n>   that we failed to find corresponding lines in our parents.\n>\n> The -M option affects what happens between the second and the third step.\n> We try to see if the lines that we did not pass blame to <rev>^$n might\n> have come from <rev>^$n by running diff between the remainder and the blob\n> in <rev>^$n *again*.  This lets us catch code movement within the blob,\n> hence the name of the option -M.\n\nI think here, not only the code movement, but also the copies will be found too.\nPlease correct me if I am wrong here. :-)\n\n> The -C option affects the choice of the blob in <rev>^$n.  Usually, we\n> internally run an equivalent of \"git diff -M <rev>^$n <rev>\" to notice\n> that the file F that we are analyzing used to be called F' in $n-th\n> parent, and run the diff against it, but -C allows us to check with paths\n> other than that, and additional -C enlarges the search space.  This is to\n> notice code movement (with a single -C) or copies (with more -Cs) across\n> paths.\n>\n> For illustrated description, read the classic:\n>\n>    http://thread.gmane.org/gmane.comp.version-control.git/28826\n\nThanks a lot for providing this reference. It really helps me too much\nto understand how blame works. I will try to re-read the whole code\naccording the description here. ;-)\n\nRegards!\nBo\n"}]}