{"thread":{"id":"52328","subject":"A new idea to extend git-blame","startedAt":"2019-11-25T12:42:10Z","lastAt":"2019-11-27T13:38:49Z","messageCount":8,"participants":["Chen Bin","Jeff King","chen bin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"386982","messageId":"87o8x06sbw.fsf@sydneypc","threadId":"52328","inReplyTo":null,"subject":"A new idea to extend git-blame","fromName":"Chen Bin","fromEmail":"chenbin.sh@gmail.com","sentAt":"2019-11-25T12:41:55Z","receivedAt":"2019-11-25T12:42:10Z","isPatch":false,"sender":{"key":"chenbin.sh@gmail.com","avatar":"https://avatars.githubusercontent.com/u/184553?v=4"},"body":"I already implemented the idea in Emacs Lisp. See,\n\nhttp://blog.binchen.org/posts/effective-git-blame-in-emacs.html\n\nI tested at https://github.com/redguardtoo/test-git-blame\n\nLooks it works.\n\nThe only issue is Lisp is slow in big code base.\n\nSo I'm thinking I could re-implement it in C instead.\n\nMy question is, *who can I contact to understand git-blame?\n\nI'm experienced at C but need some expert's guide.\n\nThe key algorithm is simple,\n\nThe algorithm only works for one line blame and the user must\nselect text inside the line first.\n\nStep 1, `git blame -L6,1 --porcelain -- hello.js` output,\n\n    4f87408612e0dacfd89a1cd2515944e21cf68561 6 6 1\n    skip...\n    filename hello.js\n     doit({bad: 'destroy world', good: 'hello world', ...});\n\nI got the commit id (1st column), the line number (2nd column),\nfile name (hello.js) and the code line (last line).\n\nStep 2, if the code line does not contain the selected text, the\n  recursive search stops\n\nStep 3, or else use commit id, line number and file name to build\n  new git blame cli, like,\n\n`git blame -L line-num,1 --porcelain 4f8740^ file-name`\n\nStep 4, execute new git blame command and start from Step 1\n\nHere is my first commit (added some debug code),\n\nhttps://github.com/redguardtoo/git/commit/d01d26f2df\n\n-- \nBest Regards,\nChen Bin\n\n--\nHelp me, help you\n"},{"id":"386991","messageId":"20191125141635.GD494@sigill.intra.peff.net","threadId":"52328","inReplyTo":"87o8x06sbw.fsf@sydneypc","subject":"Re: A new idea to extend git-blame","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-11-25T14:16:35Z","receivedAt":"2019-11-25T14:16:37Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Nov 25, 2019 at 11:41:55PM +1100, Chen Bin wrote:\n\n> The key algorithm is simple,\n> \n> The algorithm only works for one line blame and the user must\n> select text inside the line first.\n> \n> Step 1, `git blame -L6,1 --porcelain -- hello.js` output,\n> \n>     4f87408612e0dacfd89a1cd2515944e21cf68561 6 6 1\n>     skip...\n>     filename hello.js\n>      doit({bad: 'destroy world', good: 'hello world', ...});\n> \n> I got the commit id (1st column), the line number (2nd column),\n> file name (hello.js) and the code line (last line).\n> \n> Step 2, if the code line does not contain the selected text, the\n>   recursive search stops\n> \n> Step 3, or else use commit id, line number and file name to build\n>   new git blame cli, like,\n> \n> `git blame -L line-num,1 --porcelain 4f8740^ file-name`\n> \n> Step 4, execute new git blame command and start from Step 1\n\nThis sounds a lot like how git-log's \"-L\" option works, which tries to\nfind the history of a line over many changes.\n\nIt's also similar to the \"re-blame from parent\" feature of many blame\nviewers. There we have a human in the loop saying \"no, this is not quite\nthe change I'm looking for; go back further\".\n\n-Peff\n"},{"id":"387074","messageId":"CAAE-R+8betprfFOH+m_mMATX2mODHQ8pFUpLo4tyLVBVAVtySg@mail.gmail.com","threadId":"52328","inReplyTo":"20191125141635.GD494@sigill.intra.peff.net","subject":"Re: A new idea to extend git-blame","fromName":"chen bin","fromEmail":"chenbin.sh@gmail.com","sentAt":"2019-11-26T04:55:14Z","receivedAt":"2019-11-26T04:55:28Z","isPatch":false,"sender":{"key":"chenbin.sh@gmail.com","avatar":"https://avatars.githubusercontent.com/u/184553?v=4"},"body":"I re-tested `git log -L20,20:README.md` in git's own repo with HEAD\nd01d26f2df. Looks git log is not what I expected. The output contains\nmany unrelated commits. So it will be slow in real project.\n\nA recursive blame with the algorithm I suggest will get correct commit\nin short time. So my suggestion still hold.\n\nI could submit a patch to enhance blame.\n\nOn Tue, Nov 26, 2019 at 1:16 AM Jeff King <peff@peff.net> wrote:\n>\n> On Mon, Nov 25, 2019 at 11:41:55PM +1100, Chen Bin wrote:\n>\n> > The key algorithm is simple,\n> >\n> > The algorithm only works for one line blame and the user must\n> > select text inside the line first.\n> >\n> > Step 1, `git blame -L6,1 --porcelain -- hello.js` output,\n> >\n> >     4f87408612e0dacfd89a1cd2515944e21cf68561 6 6 1\n> >     skip...\n> >     filename hello.js\n> >      doit({bad: 'destroy world', good: 'hello world', ...});\n> >\n> > I got the commit id (1st column), the line number (2nd column),\n> > file name (hello.js) and the code line (last line).\n> >\n> > Step 2, if the code line does not contain the selected text, the\n> >   recursive search stops\n> >\n> > Step 3, or else use commit id, line number and file name to build\n> >   new git blame cli, like,\n> >\n> > `git blame -L line-num,1 --porcelain 4f8740^ file-name`\n> >\n> > Step 4, execute new git blame command and start from Step 1\n>\n> This sounds a lot like how git-log's \"-L\" option works, which tries to\n> find the history of a line over many changes.\n>\n> It's also similar to the \"re-blame from parent\" feature of many blame\n> viewers. There we have a human in the loop saying \"no, this is not quite\n> the change I'm looking for; go back further\".\n>\n> -Peff\n\n\n\n-- \nhelp me, help you.\n"},{"id":"387075","messageId":"CAAE-R+8dqbxWr9an63OGCL2g1sm1h-ds3yKrzz7Shwq3UyfWxQ@mail.gmail.com","threadId":"52328","inReplyTo":"CAAE-R+8betprfFOH+m_mMATX2mODHQ8pFUpLo4tyLVBVAVtySg@mail.gmail.com","subject":"Re: A new idea to extend git-blame","fromName":"chen bin","fromEmail":"chenbin.sh@gmail.com","sentAt":"2019-11-26T05:36:13Z","receivedAt":"2019-11-26T05:36:27Z","isPatch":false,"sender":{"key":"chenbin.sh@gmail.com","avatar":"https://avatars.githubusercontent.com/u/184553?v=4"},"body":"The problem of recursive blaming with 3rd party script is it's slow.\nThe script have to restart git process multiple times. Besides, as I\nalready did in Emacs (see\nhttps://github.com/redguardtoo/vc-msg/commit/1f7775f951fdd9e6571afbb3a767c42d20617f52),\nit's still lots of code.\n\nSo if it's possible to use a simple cli option like `git blame\n-S\"text\"`to do the same thing, it would be easier to migrate vc-msg's\nfunctionality to other text editors.\n\nOn Tue, Nov 26, 2019 at 3:55 PM chen bin <chenbin.sh@gmail.com> wrote:\n>\n> I re-tested `git log -L20,20:README.md` in git's own repo with HEAD\n> d01d26f2df. Looks git log is not what I expected. The output contains\n> many unrelated commits. So it will be slow in real project.\n>\n> A recursive blame with the algorithm I suggest will get correct commit\n> in short time. So my suggestion still hold.\n>\n> I could submit a patch to enhance blame.\n>\n> On Tue, Nov 26, 2019 at 1:16 AM Jeff King <peff@peff.net> wrote:\n> >\n> > On Mon, Nov 25, 2019 at 11:41:55PM +1100, Chen Bin wrote:\n> >\n> > > The key algorithm is simple,\n> > >\n> > > The algorithm only works for one line blame and the user must\n> > > select text inside the line first.\n> > >\n> > > Step 1, `git blame -L6,1 --porcelain -- hello.js` output,\n> > >\n> > >     4f87408612e0dacfd89a1cd2515944e21cf68561 6 6 1\n> > >     skip...\n> > >     filename hello.js\n> > >      doit({bad: 'destroy world', good: 'hello world', ...});\n> > >\n> > > I got the commit id (1st column), the line number (2nd column),\n> > > file name (hello.js) and the code line (last line).\n> > >\n> > > Step 2, if the code line does not contain the selected text, the\n> > >   recursive search stops\n> > >\n> > > Step 3, or else use commit id, line number and file name to build\n> > >   new git blame cli, like,\n> > >\n> > > `git blame -L line-num,1 --porcelain 4f8740^ file-name`\n> > >\n> > > Step 4, execute new git blame command and start from Step 1\n> >\n> > This sounds a lot like how git-log's \"-L\" option works, which tries to\n> > find the history of a line over many changes.\n> >\n> > It's also similar to the \"re-blame from parent\" feature of many blame\n> > viewers. There we have a human in the loop saying \"no, this is not quite\n> > the change I'm looking for; go back further\".\n> >\n> > -Peff\n>\n>\n>\n> --\n> help me, help you.\n\n\n\n-- \nhelp me, help you.\n"},{"id":"387132","messageId":"CAAE-R+8yZOchnsa-au+w4JveCQffw9bpGZ54oL+DApa8Y094=Q@mail.gmail.com","threadId":"52328","inReplyTo":"CAAE-R+8dqbxWr9an63OGCL2g1sm1h-ds3yKrzz7Shwq3UyfWxQ@mail.gmail.com","subject":"Re: A new idea to extend git-blame","fromName":"chen bin","fromEmail":"chenbin.sh@gmail.com","sentAt":"2019-11-27T07:32:37Z","receivedAt":"2019-11-27T07:32:51Z","isPatch":false,"sender":{"key":"chenbin.sh@gmail.com","avatar":"https://avatars.githubusercontent.com/u/184553?v=4"},"body":"HI, Jeff,\nJust double checking, the feature I suggested is fine, right? I will\nsend the patch asap. It may take 2 weeks to implement.\n\nOn Tue, Nov 26, 2019 at 4:36 PM chen bin <chenbin.sh@gmail.com> wrote:\n>\n> The problem of recursive blaming with 3rd party script is it's slow.\n> The script have to restart git process multiple times. Besides, as I\n> already did in Emacs (see\n> https://github.com/redguardtoo/vc-msg/commit/1f7775f951fdd9e6571afbb3a767c42d20617f52),\n> it's still lots of code.\n>\n> So if it's possible to use a simple cli option like `git blame\n> -S\"text\"`to do the same thing, it would be easier to migrate vc-msg's\n> functionality to other text editors.\n>\n> On Tue, Nov 26, 2019 at 3:55 PM chen bin <chenbin.sh@gmail.com> wrote:\n> >\n> > I re-tested `git log -L20,20:README.md` in git's own repo with HEAD\n> > d01d26f2df. Looks git log is not what I expected. The output contains\n> > many unrelated commits. So it will be slow in real project.\n> >\n> > A recursive blame with the algorithm I suggest will get correct commit\n> > in short time. So my suggestion still hold.\n> >\n> > I could submit a patch to enhance blame.\n> >\n> > On Tue, Nov 26, 2019 at 1:16 AM Jeff King <peff@peff.net> wrote:\n> > >\n> > > On Mon, Nov 25, 2019 at 11:41:55PM +1100, Chen Bin wrote:\n> > >\n> > > > The key algorithm is simple,\n> > > >\n> > > > The algorithm only works for one line blame and the user must\n> > > > select text inside the line first.\n> > > >\n> > > > Step 1, `git blame -L6,1 --porcelain -- hello.js` output,\n> > > >\n> > > >     4f87408612e0dacfd89a1cd2515944e21cf68561 6 6 1\n> > > >     skip...\n> > > >     filename hello.js\n> > > >      doit({bad: 'destroy world', good: 'hello world', ...});\n> > > >\n> > > > I got the commit id (1st column), the line number (2nd column),\n> > > > file name (hello.js) and the code line (last line).\n> > > >\n> > > > Step 2, if the code line does not contain the selected text, the\n> > > >   recursive search stops\n> > > >\n> > > > Step 3, or else use commit id, line number and file name to build\n> > > >   new git blame cli, like,\n> > > >\n> > > > `git blame -L line-num,1 --porcelain 4f8740^ file-name`\n> > > >\n> > > > Step 4, execute new git blame command and start from Step 1\n> > >\n> > > This sounds a lot like how git-log's \"-L\" option works, which tries to\n> > > find the history of a line over many changes.\n> > >\n> > > It's also similar to the \"re-blame from parent\" feature of many blame\n> > > viewers. There we have a human in the loop saying \"no, this is not quite\n> > > the change I'm looking for; go back further\".\n> > >\n> > > -Peff\n> >\n> >\n> >\n> > --\n> > help me, help you.\n>\n>\n>\n> --\n> help me, help you.\n\n\n\n-- \nhelp me, help you.\n"},{"id":"387140","messageId":"20191127113007.GB22221@sigill.intra.peff.net","threadId":"52328","inReplyTo":"CAAE-R+8yZOchnsa-au+w4JveCQffw9bpGZ54oL+DApa8Y094=Q@mail.gmail.com","subject":"Re: A new idea to extend git-blame","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-11-27T11:30:07Z","receivedAt":"2019-11-27T11:30:10Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Nov 27, 2019 at 06:32:37PM +1100, chen bin wrote:\n\n> Just double checking, the feature I suggested is fine, right? I will\n> send the patch asap. It may take 2 weeks to implement.\n\nTo be clear, I can't say whether a patch is fine or not without seeing\nthe patch. :)\n\nI'm not entirely sure I understand what you're proposing to implement.\nBut if it's of interest to you, maybe it makes sense to see if you can\nmake it work to your satisfaction, and then we can all look at the patch\nand what it does to see if it makes sense to include in Git?\n\n> > > I re-tested `git log -L20,20:README.md` in git's own repo with HEAD\n> > > d01d26f2df. Looks git log is not what I expected. The output contains\n> > > many unrelated commits. So it will be slow in real project.\n\nLooking at the output from that command, the issue is that it's\nimperfect to decide which lines in the pre- and post-image correspond to\neach other. The first commit is:\n\n  diff --git a/README.md b/README.md\n  --- a/README.md\n  +++ b/README.md\n  @@ -26,3 +26,1 @@\n  -See Documentation/gittutorial.txt to get started, then see\n  -Documentation/giteveryday.txt for a useful minimum set of commands, and\n  -Documentation/git-commandname.txt for documentation of each command.\n  +See [Documentation/gittutorial.txt][] to get started, then see\n\nat which point we consider all three of the pre-image lines to be\npotentially interestnig. And then the next commit:\n\n  diff --git a/README b/README\n  --- a/README\n  +++ b/README\n  @@ -29,3 +29,3 @@\n   See Documentation/gittutorial.txt to get started, then see\n  -Documentation/everyday.txt for a useful minimum set of commands, and\n  +Documentation/giteveryday.txt for a useful minimum set of commands, and\n   Documentation/git-commandname.txt for documentation of each command.\n\ntouches one of those lines, and so forth. A human might see that in the\nfirst hunk, it was probably the first line of the hunk that was\ninteresting to keep following backwards. But I don't think it can be\ndone automatically (which is why manual \"reblame from parent\" is still a\nuseful technique).\n\nIt sounds like your suggestion is to take some anchor text on the line\nto decide which lines to keep following. But then it sounds a lot more\nlike a \"log -L\" feature than a git-blame feature.\n\n-Peff\n"},{"id":"387145","messageId":"CAAE-R+8neOxJTt+gUrh0JeftaOU1jPKgV2_3NS2KbMTMqdfL7Q@mail.gmail.com","threadId":"52328","inReplyTo":"20191127113007.GB22221@sigill.intra.peff.net","subject":"Re: A new idea to extend git-blame","fromName":"chen bin","fromEmail":"chenbin.sh@gmail.com","sentAt":"2019-11-27T12:18:52Z","receivedAt":"2019-11-27T12:19:07Z","isPatch":false,"sender":{"key":"chenbin.sh@gmail.com","avatar":"https://avatars.githubusercontent.com/u/184553?v=4"},"body":"Got it. I will try to finish the patch first.\n\nOn Wed, Nov 27, 2019 at 10:30 PM Jeff King <peff@peff.net> wrote:\n>\n> On Wed, Nov 27, 2019 at 06:32:37PM +1100, chen bin wrote:\n>\n> > Just double checking, the feature I suggested is fine, right? I will\n> > send the patch asap. It may take 2 weeks to implement.\n>\n> To be clear, I can't say whether a patch is fine or not without seeing\n> the patch. :)\n>\n> I'm not entirely sure I understand what you're proposing to implement.\n> But if it's of interest to you, maybe it makes sense to see if you can\n> make it work to your satisfaction, and then we can all look at the patch\n> and what it does to see if it makes sense to include in Git?\n>\n> > > > I re-tested `git log -L20,20:README.md` in git's own repo with HEAD\n> > > > d01d26f2df. Looks git log is not what I expected. The output contains\n> > > > many unrelated commits. So it will be slow in real project.\n>\n> Looking at the output from that command, the issue is that it's\n> imperfect to decide which lines in the pre- and post-image correspond to\n> each other. The first commit is:\n>\n>   diff --git a/README.md b/README.md\n>   --- a/README.md\n>   +++ b/README.md\n>   @@ -26,3 +26,1 @@\n>   -See Documentation/gittutorial.txt to get started, then see\n>   -Documentation/giteveryday.txt for a useful minimum set of commands, and\n>   -Documentation/git-commandname.txt for documentation of each command.\n>   +See [Documentation/gittutorial.txt][] to get started, then see\n>\n> at which point we consider all three of the pre-image lines to be\n> potentially interestnig. And then the next commit:\n>\n>   diff --git a/README b/README\n>   --- a/README\n>   +++ b/README\n>   @@ -29,3 +29,3 @@\n>    See Documentation/gittutorial.txt to get started, then see\n>   -Documentation/everyday.txt for a useful minimum set of commands, and\n>   +Documentation/giteveryday.txt for a useful minimum set of commands, and\n>    Documentation/git-commandname.txt for documentation of each command.\n>\n> touches one of those lines, and so forth. A human might see that in the\n> first hunk, it was probably the first line of the hunk that was\n> interesting to keep following backwards. But I don't think it can be\n> done automatically (which is why manual \"reblame from parent\" is still a\n> useful technique).\n>\n> It sounds like your suggestion is to take some anchor text on the line\n> to decide which lines to keep following. But then it sounds a lot more\n> like a \"log -L\" feature than a git-blame feature.\n>\n> -Peff\n\n\n\n-- \nhelp me, help you.\n"},{"id":"387155","messageId":"CAAE-R+_yuOu6kgAcU1xP6eyERtALg0JyrKVZhRfxFQme1xfhZQ@mail.gmail.com","threadId":"52328","inReplyTo":"20191127113007.GB22221@sigill.intra.peff.net","subject":"Re: A new idea to extend git-blame","fromName":"chen bin","fromEmail":"chenbin.sh@gmail.com","sentAt":"2019-11-27T13:38:35Z","receivedAt":"2019-11-27T13:38:49Z","isPatch":false,"sender":{"key":"chenbin.sh@gmail.com","avatar":"https://avatars.githubusercontent.com/u/184553?v=4"},"body":"What I did is \"partial line blame\", select partial line, do recursive blame,\nstop when the selected text disappears.\n\nThere are screenshots at\nhttp://blog.binchen.org/posts/effective-git-blame-in-emacs.html\n\nI already implemented in Emacs Lisp. For now looks it works.\n\nI understand `git log -L20,20:README.md` can track the change before `README`\nis renamed to `README.md`. But my recursive blame code can't.\n\nThe problem is, `git log -L20,20:README.md` output too much text.\nSee https://gist.github.com/redguardtoo/a0c178350414449c45e6b67e16249000\n\nIt's difficult to track the correct commit if anchor text is generic\nwork like \"true\".\n\nFor example, the full text of line 20 in `README.md` (HEAD is d9f6f3b619 ) is,\n`See [Documentation/gittutorial.txt][] to get started, then see`\nTo detect the commit adding the word `see`, the recursive blame algorithm stops\nat commit 6164972018 because 6164972018^ rename `README` to `README.md`.\n\nThat's acceptable in real world because users can base the manual\nblame on 6164972018.\n\nBut in the output of `git log command`, there are too many\n\"occurrence\" of word \"see\" so it's\ndifficult to find the correct commit.\n\nOn Wed, Nov 27, 2019 at 10:30 PM Jeff King <peff@peff.net> wrote:\n>\n> On Wed, Nov 27, 2019 at 06:32:37PM +1100, chen bin wrote:\n>\n> > Just double checking, the feature I suggested is fine, right? I will\n> > send the patch asap. It may take 2 weeks to implement.\n>\n> To be clear, I can't say whether a patch is fine or not without seeing\n> the patch. :)\n>\n> I'm not entirely sure I understand what you're proposing to implement.\n> But if it's of interest to you, maybe it makes sense to see if you can\n> make it work to your satisfaction, and then we can all look at the patch\n> and what it does to see if it makes sense to include in Git?\n>\n> > > > I re-tested `git log -L20,20:README.md` in git's own repo with HEAD\n> > > > d01d26f2df. Looks git log is not what I expected. The output contains\n> > > > many unrelated commits. So it will be slow in real project.\n>\n> Looking at the output from that command, the issue is that it's\n> imperfect to decide which lines in the pre- and post-image correspond to\n> each other. The first commit is:\n>\n>   diff --git a/README.md b/README.md\n>   --- a/README.md\n>   +++ b/README.md\n>   @@ -26,3 +26,1 @@\n>   -See Documentation/gittutorial.txt to get started, then see\n>   -Documentation/giteveryday.txt for a useful minimum set of commands, and\n>   -Documentation/git-commandname.txt for documentation of each command.\n>   +See [Documentation/gittutorial.txt][] to get started, then see\n>\n> at which point we consider all three of the pre-image lines to be\n> potentially interestnig. And then the next commit:\n>\n>   diff --git a/README b/README\n>   --- a/README\n>   +++ b/README\n>   @@ -29,3 +29,3 @@\n>    See Documentation/gittutorial.txt to get started, then see\n>   -Documentation/everyday.txt for a useful minimum set of commands, and\n>   +Documentation/giteveryday.txt for a useful minimum set of commands, and\n>    Documentation/git-commandname.txt for documentation of each command.\n>\n> touches one of those lines, and so forth. A human might see that in the\n> first hunk, it was probably the first line of the hunk that was\n> interesting to keep following backwards. But I don't think it can be\n> done automatically (which is why manual \"reblame from parent\" is still a\n> useful technique).\n>\n> It sounds like your suggestion is to take some anchor text on the line\n> to decide which lines to keep following. But then it sounds a lot more\n> like a \"log -L\" feature than a git-blame feature.\n>\n> -Peff\n\n\n\n-- \nhelp me, help you.\n"}]}