{"thread":{"id":"36077","subject":"RFC GSoc Idea: blame: do not overly favor earlier parents","startedAt":"2014-03-06T20:02:14Z","lastAt":"2014-03-06T20:24:51Z","messageCount":3,"participants":["Junio C Hamano","David Kastrup"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"236191","messageId":"xmqq8usnxfi1.fsf@gitster.dls.corp.google.com","threadId":"36077","inReplyTo":null,"subject":"RFC GSoc Idea: blame: do not overly favor earlier parents","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-03-06T20:02:14Z","receivedAt":"2014-03-06T20:02:14Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When looking at a merge, \"git blame\" inspects the blob object names\nof all parents and if one of them exactly match the merge result,\npass the entire blame down to that parent.  This is very much in\nline with the history simplification done with \"git log\" when\ntraversing a history with merges.\n\nOn the other hand, when the blob object in the merge result and none\nof the parents match exactly, we let each parent to take as much blame\nas they can, starting from the earlier parent, and later parents get\na chance to take blame on the \"leftover bits\".\n\nCombination of the above can lead to an unexpected results.\n\nLet's say that M is a two-parent merge, M^1 == A and M^2 == B, and\nthat M:path == B:path != A:path (i.e. the merge result matches its\nsecond parent exactly).  The entire contents of the path is blamed\nto the history leading to B; the history leading to A but not\ninvolved in B will not get any blame.\n\nNow, imagine if you amend M to create N, to add a single line at the\nend of path.  M:path != N:path but there is very small difference\nbetween the two.  That means B:path != N:path but the difference\nbetween this merged result and the second parent is very small.\n\nBecause we give the chance to get blamed for the whole thing to the\nfirst parent, however, A will grab blame for all the lines that are\ncommon between A:path and B:path.  For the lines that are the same\nbetween M:path and N:path, ideally, we should get identical results,\nbut it results in a very inconsistent behaviour.\n\nUpdate blame.c::pass_blame() and give an option to arrange the list\nof \"scapegoats\" in the order that are similar to the end result, in\norder to address this issue.  That way, when blaming N:path, we will\ninspect B:path first and let it grab as much blame, as it would happen\nwhen we started the blame for M:path.\n"},{"id":"236193","messageId":"87siqvcc30.fsf@fencepost.gnu.org","threadId":"36077","inReplyTo":"xmqq8usnxfi1.fsf@gitster.dls.corp.google.com","subject":"Re: RFC GSoc Idea: blame: do not overly favor earlier parents","fromName":"David Kastrup","fromEmail":"dak@gnu.org","sentAt":"2014-03-06T20:21:39Z","receivedAt":"2014-03-06T20:21:39Z","isPatch":false,"sender":{"key":"dak@gnu.org","avatar":"https://avatars.githubusercontent.com/u/52141349?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> When looking at a merge, \"git blame\" inspects the blob object names\n> of all parents and if one of them exactly match the merge result,\n> pass the entire blame down to that parent.  This is very much in\n> line with the history simplification done with \"git log\" when\n> traversing a history with merges.\n\n[...]\n\n> Now, imagine if you amend M to create N, to add a single line at the\n> end of path.  M:path != N:path but there is very small difference\n> between the two.  That means B:path != N:path but the difference\n> between this merged result and the second parent is very small.\n\nThat sounds very much like\n\ncommit d5df1593f27bfceab807242a538cb3fa01256efd\nMerge: 7144168 0b4e246\nAuthor: Junio C Hamano <gitster@pobox.com>\nDate:   Fri Feb 28 13:51:19 2014 -0800\n\n    Merge branch 'bl/blame-full-history' into pu\n    \n    By disabling the tree-same optimization (which is consistent with\n    the default behaviour of \"git log\"-family of commands), make \"git\n    blame\" sometimes produce different result from the original code.\n    \n    Because the \"git blame\" output can give result for each line from\n    only one lineage of the history, however, this can be only useful\n    when you are lucky---unlike \"--full-history\" of \"git log\"-family,\n    where we can show commits from both lineages of histories with an\n    equal weight.  See $gmane/240392 for more detailed discussion.\n    \n    * bl/blame-full-history:\n      blame: new option --prefer-first to better handle merged cherry-picks\n\n-- \nDavid Kastrup\n"},{"id":"236195","messageId":"xmqq4n3bxegc.fsf@gitster.dls.corp.google.com","threadId":"36077","inReplyTo":"87siqvcc30.fsf@fencepost.gnu.org","subject":"Re: RFC GSoc Idea: blame: do not overly favor earlier parents","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-03-06T20:24:51Z","receivedAt":"2014-03-06T20:24:51Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"David Kastrup <dak@gnu.org> writes:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>> When looking at a merge, \"git blame\" inspects the blob object names\n>> of all parents and if one of them exactly match the merge result,\n>> pass the entire blame down to that parent.  This is very much in\n>> line with the history simplification done with \"git log\" when\n>> traversing a history with merges.\n>\n> [...]\n>\n>> Now, imagine if you amend M to create N, to add a single line at the\n>> end of path.  M:path != N:path but there is very small difference\n>> between the two.  That means B:path != N:path but the difference\n>> between this merged result and the second parent is very small.\n>\n> That sounds very much like\n>\n> commit d5df1593f27bfceab807242a538cb3fa01256efd\n> Merge: 7144168 0b4e246\n> Author: Junio C Hamano <gitster@pobox.com>\n> Date:   Fri Feb 28 13:51:19 2014 -0800\n>\n>     Merge branch 'bl/blame-full-history' into pu\n\nThat one was an attempt to solve the right issue in a wrong way,\nmade things worse by breaking the consistency with the history\nsimplification of \"git log\".\n\nThe \"Idea\" is to solve it in the way that is still consistent with\nthe usual history simplification.\n"}]}