{"thread":{"id":"17935","subject":"git-blame and finding previous version of a line","startedAt":"2009-02-21T14:39:42Z","lastAt":"2009-02-22T16:48:36Z","messageCount":2,"participants":["Jakub Narebski","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"105719","messageId":"200902211539.43312.jnareb@gmail.com","threadId":"17935","inReplyTo":null,"subject":"git-blame and finding previous version of a line","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-02-21T14:39:42Z","receivedAt":"2009-02-21T14:39:42Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano <gitster@pobox.com> wrote\nin \"What's cooking in git.git (Feb 2009, #06; Wed, 18)\"\n\n> * jc/blame (Wed Jun 4 22:58:40 2008 -0700) 2 commits\n>  + blame: show \"previous\" information in --porcelain/--incremental\n>    format\n>  + git-blame: refactor code to emit \"porcelain format\" output\n>\n> This gives Porcelains (like gitweb) the information on the commit\n> _before_ the one that the final blame is laid on, which should save\n> them one rev-parse to dig further.  The line number in the \"previous\"\n> information may need refining, and sanity checking code for reference\n> counting may need to be resurrected before this can move forward.\n>\n> I thought recent tig discussion may blow new life into it, but is\n> this unneeded?  If so I'd rather revert it (or discard after 1.6.2).\n\nThe commit message for second patch in this series has the following:\n\n   blame: show \"previous\" information in --porcelain/--incremental format\n    \n   When the final blame is laid for a line to a <commit, path> pair, it also\n   gives a \"previous\" information to --porcelain and --incremental output\n   format.  It gives the parent commit of the blamed commit, _and_ a path in\n   that parent commit that corresponds to the blamed path --- in short, it is\n   the origin that would have been blamed (or passed blame through) for the\n   line _if_ the blamed commit did not change that line.\n\n(The patch itself doesn't include update to the documentation.)  This\nI guess mean that --porcelain and --incremental output have additional\nheader:\n\n   \"previous\" <sha-1 of parent> <whitespace-quoted-filename>\n\nI also guess that it is a merge commit that got blamed (because it was\nevil merge, otherwise one of parents or its descendants would get the\nblame) we would get two or more \"previous\" info lines, in the order of\nordering of parents.\n\n\nI assume that filename in \"previous\" info can differ from filename in\nblamed commit only wrt. wholesame filename detection, and does not do\ndetection of code fragment movements by itself... or does it?\n\nThis info would be even more helpful for gitweb that I thought because\nof 'filename' part; we can simply relax refname restrictions and use\n<blamed commit>^ or <blamed commit>^<n> for 'hb' parameter, but filename\ngives some troubles (although it should happen rarely). Well, in one of\nsolutions I thought of there was intermediate step where gitweb resolved\n<ref>^ to <sha1>, and did HTTP redirection; in this solution there is\na place where gitweb can find previous filename (filename in <rev>^,\ngiven filename in <rev>), but it would be a mess.\n\n\nLuben Tuikov in 244a70e6 (Blame \"linenr\" link jumps to previous state\nat \"orig_lineno\") made gitweb link to previous version of a file (using\nalways first parent), for better data mining, or in other words to be\nable to follow history of a given line.  Current code makes a few\nassumptions:\n * we are always interested in first parent; this matters only for\n   'evil merges', it the merge commit itself was blamed, which should\n   be fairly rare case\n * the name of a file is the same in parent as in blamed commit; we\n   would have to run git-diff-tree to check it without proposed\n   \"previous\" header in blame output, all for rare case of file rename,\n   or complicate a bit resolving filename after clicking link\n * previous version of given line is at the same position in a file\n   in a parent; or at least it is close\n\nIt is the last assumption that is, I think, hardest to correct.\n\nWhat algorithm do you propose to find previous version of a line? It is\nnot a question with definitive answer, I think, so some heuristic would\nbe required. Previous version of a line might not even exists! (in that\ncase we would probably want to be in the place it is inserted). \nFortunately this is a situation where approximation is good enough.\n\n\n(I don't know if git-blame has access to textual diff, or at least\ninformation in chunk headers when calculating blame information, so\nI don't know if the following algorithm is feasible.)\n\nI propose the following algorithm:\n * find a hunk in textual diff which postimage contains current\n   version of a line: searching hunk headers for line number should\n   be enough here\n * get line numbers for corresponding preimage (I'm not sure if this\n   algorithm wouldn't fail here if code movement detection is enabled)\n * either find most similar line in preimage, or calculate (perhaps\n   with linear interpolation) where given line number in postimage\n   line range corresponds to in preimage line range\n\nWhat do you think about this algorithm? Is it good enough?\n\n\nP.S. I think that going to the blamed commit version might be also\n     interesting: you can check how the neighbourhood if given line\n     changed, isn't it?\n-- \nJakub Narebski\nPoland\n"},{"id":"105776","messageId":"7vy6vy2za3.fsf@gitster.siamese.dyndns.org","threadId":"17935","inReplyTo":"200902211539.43312.jnareb@gmail.com","subject":"Re: git-blame and finding previous version of a line","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-22T16:48:36Z","receivedAt":"2009-02-22T16:48:36Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> What algorithm do you propose to find previous version of a line? It is\n> not a question with definitive answer, I think, so some heuristic would\n> be required. Previous version of a line might not even exists! (in that\n> case we would probably want to be in the place it is inserted). \n> Fortunately this is a situation where approximation is good enough.\n\nI think Peff and Jonas had discussion on this in the previous thread on\ntig.\n"}]}