{"thread":{"id":"47342","subject":"git blame --reverse doesn't find line in HEAD","startedAt":"2017-11-29T08:07:18Z","lastAt":"2017-12-07T17:03:25Z","messageCount":5,"participants":["Nick Snyder","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"333773","messageId":"CA+SQVf1W6BhNyB6bGxh7WfCwb6+E3pNjHLeS4xDYPJ6BLT8cng@mail.gmail.com","threadId":"47342","inReplyTo":null,"subject":"git blame --reverse doesn't find line in HEAD","fromName":"Nick Snyder","fromEmail":"nick@sourcegraph.com","sentAt":"2017-11-29T08:06:51Z","receivedAt":"2017-11-29T08:07:18Z","isPatch":false,"sender":{"key":"nick@sourcegraph.com","avatar":"https://gravatar.com/avatar/dea6a0138bee7ed02d7fbd7fa2a5bac82ceca06bf436c0ce5dfc8bbfbc5399d7?d=mp&s=160"},"body":"I have a repo that reproduces a behavior with `git blame --reverse`\nthat surprises me. https://github.com/nicksnyder/git-blame-bug\n\nThe readme explains the observed behavior and what I expected to\nhappen. I will inline the readme at the bottom of this message for\nconvenience.\n\nAm I misunderstanding --reverse or is this a bug?\n\nThanks!\nNick\n\n$ git --version\ngit version 2.15.0\n\nBlame of L465 in Tree.tsx at HEAD (ca0fb5) points to L463 at 199ee7\n\n$ git blame -p -L465,465 Tree.tsx\n199ee75d1240ae72cd965f62aceeb301ab64e1bd 463 465 1\nfilename Tree.tsx\n            public shouldComponentUpdate(nextProps: TileProps): boolean {\n\nEXPECTED: Reverse blame of L463 at 199ee7 points to L465 at the\nlastest commit in the repo (at least ca0fb5).\nACTUAL: Reverse blame of L463 at 199ee7 points to L463 at 199ee7.\n\n$ git blame -p -L463,463 --reverse 199ee7.. Tree.tsx\n199ee75d1240ae72cd965f62aceeb301ab64e1bd 463 463 1\nboundary\nprevious ca0fb5a2d61cb16909bcb06f49dd5448a26f32b1 Tree.tsx\nfilename Tree.tsx\n            public shouldComponentUpdate(nextProps: TileProps): boolean {\n\nThe line in question is in the diff (git diff 199ee7..ca0fb5), but\nthat particular line is neither added nor deleted, so I don't know why\nblame would think it is deleted.\n\nRelevant hunk in diff:\n\n@@ -452,28 +462,17 @@ export class LayerTile extends\nReact.Component<TileProps, {}> {\n         }\n     }\n\n-    public validTokenRange(props: TileProps): boolean {\n-        if (props.selectedPath === '') {\n-            return true\n-        }\n-        const token = props.selectedPath.split('/').pop()!\n-        return token >= this.first && token <= this.last\n-    }\n-\n     public shouldComponentUpdate(nextProps: TileProps): boolean {\n-        const lastValid = this.validTokenRange(this.props)\n-        const nextValid = this.validTokenRange(nextProps)\n-        if (!lastValid && !nextValid) {\n-            // short circuit\n-            return false\n+        if (isEqualOrAncestor(this.props.selectedDir,\nthis.props.currSubpath)) {\n+            return true\n         }\n-        if (isEqualOrAncestor(this.props.selectedDir,\nthis.props.currSubpath) && lastValid) {\n+        if (nextProps.selectedDir === nextProps.currSubpath) {\n             return true\n         }\n-        if (nextProps.selectedDir === nextProps.currSubpath &&\nthis.validTokenRange(nextProps)) {\n+        if (getParentDir(nextProps.selectedDir) === nextProps.currSubpath) {\n             return true\n         }\n-        if (getParentDir(nextProps.selectedDir) ===\nnextProps.currSubpath && this.validTokenRange(nextProps)) {\n+        if (!isEqual(nextProps.pathSplits, this.props.pathSplits)) {\n             return true\n         }\n         return false\n"},{"id":"334249","messageId":"CA+SQVf24rcQ1iKAQBW0Ky7Qm8zuF3Esw8qMKvG+KCbCA-mCcfA@mail.gmail.com","threadId":"47342","inReplyTo":"CA+SQVf1W6BhNyB6bGxh7WfCwb6+E3pNjHLeS4xDYPJ6BLT8cng@mail.gmail.com","subject":"Re: git blame --reverse doesn't find line in HEAD","fromName":"Nick Snyder","fromEmail":"nick@sourcegraph.com","sentAt":"2017-12-06T15:40:35Z","receivedAt":"2017-12-06T15:41:04Z","isPatch":false,"sender":{"key":"nick@sourcegraph.com","avatar":"https://gravatar.com/avatar/dea6a0138bee7ed02d7fbd7fa2a5bac82ceca06bf436c0ce5dfc8bbfbc5399d7?d=mp&s=160"},"body":"This can be reproduced on Linux and Mac. This behavior seems to be a bug.\n\nOn Wed, Nov 29, 2017 at 12:06 AM, Nick Snyder <nick@sourcegraph.com> wrote:\n> I have a repo that reproduces a behavior with `git blame --reverse`\n> that surprises me. https://github.com/nicksnyder/git-blame-bug\n>\n> The readme explains the observed behavior and what I expected to\n> happen. I will inline the readme at the bottom of this message for\n> convenience.\n>\n> Am I misunderstanding --reverse or is this a bug?\n>\n> Thanks!\n> Nick\n>\n> $ git --version\n> git version 2.15.0\n>\n> Blame of L465 in Tree.tsx at HEAD (ca0fb5) points to L463 at 199ee7\n>\n> $ git blame -p -L465,465 Tree.tsx\n> 199ee75d1240ae72cd965f62aceeb301ab64e1bd 463 465 1\n> filename Tree.tsx\n>             public shouldComponentUpdate(nextProps: TileProps): boolean {\n>\n> EXPECTED: Reverse blame of L463 at 199ee7 points to L465 at the\n> lastest commit in the repo (at least ca0fb5).\n> ACTUAL: Reverse blame of L463 at 199ee7 points to L463 at 199ee7.\n>\n> $ git blame -p -L463,463 --reverse 199ee7.. Tree.tsx\n> 199ee75d1240ae72cd965f62aceeb301ab64e1bd 463 463 1\n> boundary\n> previous ca0fb5a2d61cb16909bcb06f49dd5448a26f32b1 Tree.tsx\n> filename Tree.tsx\n>             public shouldComponentUpdate(nextProps: TileProps): boolean {\n>\n> The line in question is in the diff (git diff 199ee7..ca0fb5), but\n> that particular line is neither added nor deleted, so I don't know why\n> blame would think it is deleted.\n>\n> Relevant hunk in diff:\n>\n> @@ -452,28 +462,17 @@ export class LayerTile extends\n> React.Component<TileProps, {}> {\n>          }\n>      }\n>\n> -    public validTokenRange(props: TileProps): boolean {\n> -        if (props.selectedPath === '') {\n> -            return true\n> -        }\n> -        const token = props.selectedPath.split('/').pop()!\n> -        return token >= this.first && token <= this.last\n> -    }\n> -\n>      public shouldComponentUpdate(nextProps: TileProps): boolean {\n> -        const lastValid = this.validTokenRange(this.props)\n> -        const nextValid = this.validTokenRange(nextProps)\n> -        if (!lastValid && !nextValid) {\n> -            // short circuit\n> -            return false\n> +        if (isEqualOrAncestor(this.props.selectedDir,\n> this.props.currSubpath)) {\n> +            return true\n>          }\n> -        if (isEqualOrAncestor(this.props.selectedDir,\n> this.props.currSubpath) && lastValid) {\n> +        if (nextProps.selectedDir === nextProps.currSubpath) {\n>              return true\n>          }\n> -        if (nextProps.selectedDir === nextProps.currSubpath &&\n> this.validTokenRange(nextProps)) {\n> +        if (getParentDir(nextProps.selectedDir) === nextProps.currSubpath) {\n>              return true\n>          }\n> -        if (getParentDir(nextProps.selectedDir) ===\n> nextProps.currSubpath && this.validTokenRange(nextProps)) {\n> +        if (!isEqual(nextProps.pathSplits, this.props.pathSplits)) {\n>              return true\n>          }\n>          return false\n"},{"id":"334259","messageId":"xmqqh8t3hiuq.fsf@gitster.mtv.corp.google.com","threadId":"47342","inReplyTo":"CA+SQVf24rcQ1iKAQBW0Ky7Qm8zuF3Esw8qMKvG+KCbCA-mCcfA@mail.gmail.com","subject":"Re: git blame --reverse doesn't find line in HEAD","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-12-06T17:22:21Z","receivedAt":"2017-12-06T17:22:28Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nick Snyder <nick@sourcegraph.com> writes:\n\n> This can be reproduced on Linux and Mac. This behavior seems to be a bug.\n\nCan you bisect to see when the feature stopped working as you expect?\n\nUnlike a forward blame, where the command tries to find a commit\nthat is responsible for a line being in the final result (i.e.\ntypically, HEAD), a reverse blame is not about finding a commit\nthat is responsible for a line (that used to be in the oldest\ncommit) not being in a more recent codebase.  It finds up to which\ncommit each line survived without getting touched since the oldest\ncommit in the range.\n\n"},{"id":"334262","messageId":"CA+SQVf14g4zBP14BHEZQkyeqUE5Oqif3bUVADEwBZQTSwE=bKA@mail.gmail.com","threadId":"47342","inReplyTo":"xmqqh8t3hiuq.fsf@gitster.mtv.corp.google.com","subject":"Re: git blame --reverse doesn't find line in HEAD","fromName":"Nick Snyder","fromEmail":"nick@sourcegraph.com","sentAt":"2017-12-06T18:00:14Z","receivedAt":"2017-12-06T18:00:41Z","isPatch":false,"sender":{"key":"nick@sourcegraph.com","avatar":"https://gravatar.com/avatar/dea6a0138bee7ed02d7fbd7fa2a5bac82ceca06bf436c0ce5dfc8bbfbc5399d7?d=mp&s=160"},"body":"> Can you bisect to see when the feature stopped working as you expect?\n\nI will see if I can do that but might take some time.\n\n> It finds up to which commit each line survived without getting touched since the oldest commit in the range.\n\nRight, this is where it is failing in my case.\n\nWith a history like this:\nA <- B <- C <- HEAD\n\nI have a particular line in C (HEAD) that blames to commit A.\nIf I run a git blame --reverse starting at commit A for that line, it\ndoesn't give me back C, it gives me back B instead.\nThe line is not added/deleted/moved between B and C.\n\n\n\nOn Wed, Dec 6, 2017 at 9:22 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Nick Snyder <nick@sourcegraph.com> writes:\n>\n>> This can be reproduced on Linux and Mac. This behavior seems to be a bug.\n>\n> Can you bisect to see when the feature stopped working as you expect?\n>\n> Unlike a forward blame, where the command tries to find a commit\n> that is responsible for a line being in the final result (i.e.\n> typically, HEAD), a reverse blame is not about finding a commit\n> that is responsible for a line (that used to be in the oldest\n> commit) not being in a more recent codebase.  It finds up to which\n> commit each line survived without getting touched since the oldest\n> commit in the range.\n>\n"},{"id":"334332","messageId":"CA+SQVf3LuYj-N9NaDPxRcADjgWK5DFbF8LM=6VhY9N0GnbxyyA@mail.gmail.com","threadId":"47342","inReplyTo":"CA+SQVf14g4zBP14BHEZQkyeqUE5Oqif3bUVADEwBZQTSwE=bKA@mail.gmail.com","subject":"Re: git blame --reverse doesn't find line in HEAD","fromName":"Nick Snyder","fromEmail":"nick@sourcegraph.com","sentAt":"2017-12-07T17:02:42Z","receivedAt":"2017-12-07T17:03:25Z","isPatch":false,"sender":{"key":"nick@sourcegraph.com","avatar":"https://gravatar.com/avatar/dea6a0138bee7ed02d7fbd7fa2a5bac82ceca06bf436c0ce5dfc8bbfbc5399d7?d=mp&s=160"},"body":"I built from source and was unable to find a git version where this\nhas ever worked correctly.\n\nI wasn't able to compile and test versions older than 1.6.1.\n\nConfirmed not working:\n2.15.1\n2.13.6 (Apple Git-96)\n2.0.0\n1.7.0\n1.6.3\n1.6.2\n1.6.1\n\nI updated the https://github.com/nicksnyder/git-blame-bug with a\nscript to easily reproduce.\n\nOn Wed, Dec 6, 2017 at 10:00 AM, Nick Snyder <nick@sourcegraph.com> wrote:\n>> Can you bisect to see when the feature stopped working as you expect?\n>\n> I will see if I can do that but might take some time.\n>\n>> It finds up to which commit each line survived without getting touched since the oldest commit in the range.\n>\n> Right, this is where it is failing in my case.\n>\n> With a history like this:\n> A <- B <- C <- HEAD\n>\n> I have a particular line in C (HEAD) that blames to commit A.\n> If I run a git blame --reverse starting at commit A for that line, it\n> doesn't give me back C, it gives me back B instead.\n> The line is not added/deleted/moved between B and C.\n>\n>\n>\n> On Wed, Dec 6, 2017 at 9:22 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> Nick Snyder <nick@sourcegraph.com> writes:\n>>\n>>> This can be reproduced on Linux and Mac. This behavior seems to be a bug.\n>>\n>> Can you bisect to see when the feature stopped working as you expect?\n>>\n>> Unlike a forward blame, where the command tries to find a commit\n>> that is responsible for a line being in the final result (i.e.\n>> typically, HEAD), a reverse blame is not about finding a commit\n>> that is responsible for a line (that used to be in the oldest\n>> commit) not being in a more recent codebase.  It finds up to which\n>> commit each line survived without getting touched since the oldest\n>> commit in the range.\n>>\n"}]}