{"thread":{"id":"55912","subject":"[PATCH] doc: revisions: improve single range explanation","startedAt":"2021-06-13T00:54:08Z","lastAt":"2021-06-15T11:53:45Z","messageCount":11,"participants":["Felipe Contreras","Bagas Sanjaya","Eric Sunshine","Elijah Newren"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"427198","messageId":"20210613004434.10278-1-felipe.contreras@gmail.com","threadId":"55912","inReplyTo":null,"subject":"[PATCH] doc: revisions: improve single range explanation","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2021-06-13T00:44:34Z","receivedAt":"2021-06-13T00:54:08Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"The original explanation didn't seem clear enough to some people.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n Documentation/revisions.txt | 22 +++++++++++-----------\n 1 file changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/Documentation/revisions.txt b/Documentation/revisions.txt\nindex f5f17b65a1..d8cf512686 100644\n--- a/Documentation/revisions.txt\n+++ b/Documentation/revisions.txt\n@@ -299,22 +299,22 @@ empty range that is both reachable and unreachable from HEAD.\n \n Commands that are specifically designed to take two distinct ranges\n (e.g. \"git range-diff R1 R2\" to compare two ranges) do exist, but\n-they are exceptions.  Unless otherwise noted, all \"git\" commands\n+they are exceptions.  Unless otherwise noted, all git commands\n that operate on a set of commits work on a single revision range.\n-In other words, writing two \"two-dot range notation\" next to each\n-other, e.g.\n \n-    $ git log A..B C..D\n+For example, if you have a linear history like this:\n \n-does *not* specify two revision ranges for most commands.  Instead\n-it will name a single connected set of commits, i.e. those that are\n-reachable from either B or D but are reachable from neither A or C.\n-In a linear history like this:\n+    ---A---B---C---D---E---F\n \n-    ---A---B---o---o---C---D\n+Doing A..F will retrieve 5 commits, and doing B..E will retrieve 3\n+commits, but doing A..F B..E will not retrieve two revision ranges\n+totalling 8 commits. Instead the starting point A gets overriden by B,\n+and the ending point of E by F, effectively becoming B..F, a single\n+revision range.\n \n-because A and B are reachable from C, the revision range specified\n-by these two dotted ranges is a single commit D.\n+With more complex graphs the result is not so simple and might result in\n+two disconnected sets of commits, but that is still considered a single\n+revision range.\n \n \n Other <rev>{caret} Parent Shorthand Notations\n-- \n2.32.0\n\n"},{"id":"427200","messageId":"4067f10f-067f-6475-8305-2e10631388c6@gmail.com","threadId":"55912","inReplyTo":"20210613004434.10278-1-felipe.contreras@gmail.com","subject":"Re: [PATCH] doc: revisions: improve single range explanation","fromName":"Bagas Sanjaya","fromEmail":"bagasdotme@gmail.com","sentAt":"2021-06-13T02:50:21Z","receivedAt":"2021-06-13T02:50:43Z","isPatch":true,"sender":{"key":"bagasdotme@gmail.com","avatar":"https://avatars.githubusercontent.com/u/40219486?v=4"},"body":"Hi,\n\nOn 13/06/21 07.44, Felipe Contreras wrote:\n> The original explanation didn't seem clear enough to some people.\n> \n> Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n> ---\n>   Documentation/revisions.txt | 22 +++++++++++-----------\n>   1 file changed, 11 insertions(+), 11 deletions(-)\n> \n> diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt\n> index f5f17b65a1..d8cf512686 100644\n> --- a/Documentation/revisions.txt\n> +++ b/Documentation/revisions.txt\n> @@ -299,22 +299,22 @@ empty range that is both reachable and unreachable from HEAD.\n>   \n>   Commands that are specifically designed to take two distinct ranges\n>   (e.g. \"git range-diff R1 R2\" to compare two ranges) do exist, but\n> -they are exceptions.  Unless otherwise noted, all \"git\" commands\n> +they are exceptions.  Unless otherwise noted, all git commands\n>   that operate on a set of commits work on a single revision range.\n> -In other words, writing two \"two-dot range notation\" next to each\n> -other, e.g.\n>   \n> -    $ git log A..B C..D\n> +For example, if you have a linear history like this:\n>   \n> -does *not* specify two revision ranges for most commands.  Instead\n> -it will name a single connected set of commits, i.e. those that are\n> -reachable from either B or D but are reachable from neither A or C.\n> -In a linear history like this:\n> +    ---A---B---C---D---E---F\n>   \n> -    ---A---B---o---o---C---D\n> +Doing A..F will retrieve 5 commits, and doing B..E will retrieve 3\n> +commits, but doing A..F B..E will not retrieve two revision ranges\n> +totalling 8 commits. Instead the starting point A gets overriden by B,\n> +and the ending point of E by F, effectively becoming B..F, a single\n> +revision range.\n> \n\n\nAFAIK, A..F means all commits from A to F. But in case of branched \nhistory like\n\n     ---A---B---C---G---H---I <- main\n                \\\n                 ---D---E---F <- mybranch\n\nthe notation main..mybranch means all commits that are reachable from \nmybranch but not from main, but the opposite (mybranch..main) means the \nopposite!\n\nSo basically the right-hand side of two dot notation specifies from what \ncommit I want to select the range, and the left-hand side specifies the \ncommit which I don't want to reach.\n\n-- \nAn old man doll... just what I always wanted! - Clara\n"},{"id":"427204","messageId":"60c577a9a1a71_3c23a208ed@natae.notmuch","threadId":"55912","inReplyTo":"4067f10f-067f-6475-8305-2e10631388c6@gmail.com","subject":"Re: [PATCH] doc: revisions: improve single range explanation","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2021-06-13T03:12:41Z","receivedAt":"2021-06-13T03:12:47Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Bagas Sanjaya wrote:\n> On 13/06/21 07.44, Felipe Contreras wrote:\n> > The original explanation didn't seem clear enough to some people.\n> > \n> > Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n> > ---\n> >   Documentation/revisions.txt | 22 +++++++++++-----------\n> >   1 file changed, 11 insertions(+), 11 deletions(-)\n> > \n> > diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt\n> > index f5f17b65a1..d8cf512686 100644\n> > --- a/Documentation/revisions.txt\n> > +++ b/Documentation/revisions.txt\n> > @@ -299,22 +299,22 @@ empty range that is both reachable and unreachable from HEAD.\n> >   \n> >   Commands that are specifically designed to take two distinct ranges\n> >   (e.g. \"git range-diff R1 R2\" to compare two ranges) do exist, but\n> > -they are exceptions.  Unless otherwise noted, all \"git\" commands\n> > +they are exceptions.  Unless otherwise noted, all git commands\n> >   that operate on a set of commits work on a single revision range.\n> > -In other words, writing two \"two-dot range notation\" next to each\n> > -other, e.g.\n> >   \n> > -    $ git log A..B C..D\n> > +For example, if you have a linear history like this:\n> >   \n> > -does *not* specify two revision ranges for most commands.  Instead\n> > -it will name a single connected set of commits, i.e. those that are\n> > -reachable from either B or D but are reachable from neither A or C.\n> > -In a linear history like this:\n> > +    ---A---B---C---D---E---F\n> >   \n> > -    ---A---B---o---o---C---D\n> > +Doing A..F will retrieve 5 commits, and doing B..E will retrieve 3\n> > +commits, but doing A..F B..E will not retrieve two revision ranges\n> > +totalling 8 commits. Instead the starting point A gets overriden by B,\n> > +and the ending point of E by F, effectively becoming B..F, a single\n> > +revision range.\n> \n> AFAIK, A..F means all commits from A to F. But in case of branched \n> history like\n> \n>      ---A---B---C---G---H---I <- main\n>                 \\\n>                  ---D---E---F <- mybranch\n> \n> the notation main..mybranch means all commits that are reachable from \n> mybranch but not from main, but the opposite (mybranch..main) means the \n> opposite!\n> \n> So basically the right-hand side of two dot notation specifies from what \n> commit I want to select the range, and the left-hand side specifies the \n> commit which I don't want to reach.\n\nYes, `A..F` is the same as `^A F`.\n\n-- \nFelipe Contreras\n"},{"id":"427205","messageId":"CAPig+cSE2h7A52drhELfZJLDEgQ1z+nEXoXhYMUSA00Z+S=OUA@mail.gmail.com","threadId":"55912","inReplyTo":"20210613004434.10278-1-felipe.contreras@gmail.com","subject":"Re: [PATCH] doc: revisions: improve single range explanation","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2021-06-13T03:32:28Z","receivedAt":"2021-06-13T03:32:58Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sat, Jun 12, 2021 at 8:44 PM Felipe Contreras\n<felipe.contreras@gmail.com> wrote:\n> The original explanation didn't seem clear enough to some people.\n>\n> Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n> ---\n> diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt\n> @@ -299,22 +299,22 @@ empty range that is both reachable and unreachable from HEAD.\n> +For example, if you have a linear history like this:\n>\n> +    ---A---B---C---D---E---F\n>\n> +Doing A..F will retrieve 5 commits, and doing B..E will retrieve 3\n> +commits, but doing A..F B..E will not retrieve two revision ranges\n> +totalling 8 commits. Instead the starting point A gets overriden by B,\n> +and the ending point of E by F, effectively becoming B..F, a single\n> +revision range.\n\ns/overriden/overridden/\n\nFor what it's worth, as a person who is far from expert at revision\nranges, I had to read this revised text five or six times and think\nabout it quite a bit to understand what it is saying, whereas with\nJunio's original[1], I understood it on the first read with only a\nlittle thought.\n\nAlso, if this explanation is aimed at newcomers, then saying only\n\"doing A..F will retrieve 5 commits\" without actually saying _which_\ncommits those are is perhaps not so helpful. A newcomer might be\nhelped more by enumerating the precise commits:\n\n    The range A..F represents five commits B, C, D, E, F, and the\n    range B..E represents three commits C, D, E, ...\n\n[1]: https://lore.kernel.org/git/xmqqv97g2svd.fsf@gitster.g/\n"},{"id":"427209","messageId":"60c588d452750_3d86c2085c@natae.notmuch","threadId":"55912","inReplyTo":"CAPig+cSE2h7A52drhELfZJLDEgQ1z+nEXoXhYMUSA00Z+S=OUA@mail.gmail.com","subject":"Re: [PATCH] doc: revisions: improve single range explanation","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2021-06-13T04:25:56Z","receivedAt":"2021-06-13T04:26:07Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Eric Sunshine wrote:\n> On Sat, Jun 12, 2021 at 8:44 PM Felipe Contreras\n> <felipe.contreras@gmail.com> wrote:\n> > The original explanation didn't seem clear enough to some people.\n> >\n> > Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n> > ---\n> > diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt\n> > @@ -299,22 +299,22 @@ empty range that is both reachable and unreachable from HEAD.\n> > +For example, if you have a linear history like this:\n> >\n> > +    ---A---B---C---D---E---F\n> >\n> > +Doing A..F will retrieve 5 commits, and doing B..E will retrieve 3\n> > +commits, but doing A..F B..E will not retrieve two revision ranges\n> > +totalling 8 commits. Instead the starting point A gets overriden by B,\n> > +and the ending point of E by F, effectively becoming B..F, a single\n> > +revision range.\n> \n> s/overriden/overridden/\n> \n> For what it's worth, as a person who is far from expert at revision\n> ranges, I had to read this revised text five or six times and think\n> about it quite a bit to understand what it is saying,\n\nCan you explain why?\n\nThis is the context: commands don't generally take two ranges:\n\n 1. Unless otherwise noted, all git commands that operate on a set of\n    commits work on a single revision range.\n\n 2. Doing A..F will retrieve 5 commits, and doing B..E will retrieve 3\n    commits, but doing A..F B..E will not retrieve two revision ranges\n    totalling 8 commits.\n\nAt this point what isn't clear? Isn't it clear that `A..F B..E` aren't\ntwo revision ranges?\n\n 3. Instead the starting point A gets overridden by B, and the ending\n    point of E by F, effectively becoming B..F, a single revision range.\n\nWhat isn't clear about that? A gets superseded by B because it's higher\nin the graph. And if you do `git log D E F` it's clear that doing\n`git log F` will get you the same thing, isn't it?\n\n> Also, if this explanation is aimed at newcomers, then saying only\n> \"doing A..F will retrieve 5 commits\" without actually saying _which_\n> commits those are is perhaps not so helpful.\n\nIt doesn't matter which specific commits are retrieved, the only thing\nthat matters is that `X op Y` is not additive.\n\n-- \nFelipe Contreras\n"},{"id":"427219","messageId":"CABPp-BE4r=Nhw2sJS++7Eh1K5rpyWgg+f8vDTf92JBayt1B_cA@mail.gmail.com","threadId":"55912","inReplyTo":"60c588d452750_3d86c2085c@natae.notmuch","subject":"Re: [PATCH] doc: revisions: improve single range explanation","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2021-06-13T07:02:18Z","receivedAt":"2021-06-13T07:03:45Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Sat, Jun 12, 2021 at 9:25 PM Felipe Contreras\n<felipe.contreras@gmail.com> wrote:\n>\n> Eric Sunshine wrote:\n> > On Sat, Jun 12, 2021 at 8:44 PM Felipe Contreras\n> > <felipe.contreras@gmail.com> wrote:\n> > > The original explanation didn't seem clear enough to some people.\n> > >\n> > > Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n> > > ---\n> > > diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt\n> > > @@ -299,22 +299,22 @@ empty range that is both reachable and unreachable from HEAD.\n> > > +For example, if you have a linear history like this:\n> > >\n> > > +    ---A---B---C---D---E---F\n> > >\n> > > +Doing A..F will retrieve 5 commits, and doing B..E will retrieve 3\n> > > +commits, but doing A..F B..E will not retrieve two revision ranges\n> > > +totalling 8 commits. Instead the starting point A gets overriden by B,\n> > > +and the ending point of E by F, effectively becoming B..F, a single\n> > > +revision range.\n> >\n> > s/overriden/overridden/\n> >\n> > For what it's worth, as a person who is far from expert at revision\n> > ranges, I had to read this revised text five or six times and think\n> > about it quite a bit to understand what it is saying,\n>\n> Can you explain why?\n\nI tend to agree with Eric.  I think the example you chose is likely to\nbe misinterpreted and your wording magnifies it.  A..F B..E simplifies\nto B..F which is *almost* the union of A..F and B..E, it's only\nmissing A.  Off-by-one errors are easy to miss.  You make it more\nlikely that they'll miss it, because there are only 6 commits total in\nthe union, and you are trying to explain why listing A..F B..E while\nnot be 8 commits, which readers can easily respond with, \"Well, of\ncourse it's not 8 commits.  There's only 6.  When you do the union\noperation, of course the duplicates go away\", and miss the actual\npoint that A got excluded.\n\nJunio's wording and example just seemed better to me here.\n\n>\n> This is the context: commands don't generally take two ranges:\n>\n>  1. Unless otherwise noted, all git commands that operate on a set of\n>     commits work on a single revision range.\n>\n>  2. Doing A..F will retrieve 5 commits, and doing B..E will retrieve 3\n>     commits, but doing A..F B..E will not retrieve two revision ranges\n>     totalling 8 commits.\n>\n> At this point what isn't clear? Isn't it clear that `A..F B..E` aren't\n> two revision ranges?\n>\n>  3. Instead the starting point A gets overridden by B, and the ending\n>     point of E by F, effectively becoming B..F, a single revision range.\n>\n> What isn't clear about that? A gets superseded by B because it's higher\n> in the graph. And if you do `git log D E F` it's clear that doing\n> `git log F` will get you the same thing, isn't it?\n>\n> > Also, if this explanation is aimed at newcomers, then saying only\n> > \"doing A..F will retrieve 5 commits\" without actually saying _which_\n> > commits those are is perhaps not so helpful.\n>\n> It doesn't matter which specific commits are retrieved, the only thing\n> that matters is that `X op Y` is not additive.\n>\n> --\n> Felipe Contreras\n"},{"id":"427227","messageId":"CAPig+cQhve3pTdrm8ZeJ8-YPJj4gWrk=BB9rLqRojXgYJrAi2Q@mail.gmail.com","threadId":"55912","inReplyTo":"60c588d452750_3d86c2085c@natae.notmuch","subject":"Re: [PATCH] doc: revisions: improve single range explanation","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2021-06-13T08:11:42Z","receivedAt":"2021-06-13T08:11:56Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Jun 13, 2021 at 12:26 AM Felipe Contreras\n<felipe.contreras@gmail.com> wrote:\n> Eric Sunshine wrote:\n> > For what it's worth, as a person who is far from expert at revision\n> > ranges, I had to read this revised text five or six times and think\n> > about it quite a bit to understand what it is saying,\n>\n> Can you explain why?\n\nProbably not to a degree which will satisfy you. And I'm not being\nflippant by saying that. I mean only that it is more than a little\ndifficult to explain why one thing \"clicks\" easily in the brain while\nsomething else doesn't. I can only relate (to some extent) what I\nexperienced while reading your revised text.\n\n> This is the context: commands don't generally take two ranges:\n>\n>  1. Unless otherwise noted, all git commands that operate on a set of\n>     commits work on a single revision range.\n>\n>  2. Doing A..F will retrieve 5 commits, and doing B..E will retrieve 3\n>     commits, but doing A..F B..E will not retrieve two revision ranges\n>     totalling 8 commits.\n>\n> At this point what isn't clear? Isn't it clear that `A..F B..E` aren't\n> two revision ranges?\n\nThe documentation stating explicitly that `A..F B..E` is not two\nranges is fine. What was difficult to understand was your explanation\nof _why_ those are not two ranges. In contrast, I had no difficulty\nunderstanding Junio's explanation of why that is not two ranges.\n\n>  3. Instead the starting point A gets overridden by B, and the ending\n>     point of E by F, effectively becoming B..F, a single revision range.\n>\n> What isn't clear about that? A gets superseded by B because it's higher\n> in the graph. And if you do `git log D E F` it's clear that doing\n> `git log F` will get you the same thing, isn't it?\n\nOne of the reasons I had to re-read your text so many times was\nbecause it was difficult to build a mental model of what you were\nsaying, and to follow along with all the \"this replaces that\" and\n\"this other thing replaces that other thing\". While doing so, I\nrepeatedly had to glance back at the original `A..F B..E` to make sure\nthe mental model I was building was correct or still made sense. The\nword \"overridden\" didn't help because I couldn't tell if, by\n\"overridden\", you meant that something got replaced by something else\nor if something was merely ignored. (Or maybe those are the same thing\nin this case, but how will a newcomer -- who is trying to learn this\nfrom scratch -- know which it is?)\n\nHowever, an even bigger problem I experienced while reading your\nrevised text is that it felt like it was trying to express some rule\nwhich the reader should internalize (\"replace this with that, and\nreplace this other thing too\") with no proper explanation of _why_ the\nrule works that way. Worse, the rule (whatever it is) never actually\nmaterialized or solidified in a way which I could understand and thus\napply to in other situations. Junio's explanation, on the other hand,\nwas simple and to the point, and (for whatever reason) clicked easily\nin my brain, such that I came away feeling that I could apply the\nknowledge immediately to other situations. On the other hand, after\nreading your proposed text, I did not feel as if I had gained any\nknowledge, and even had I picked up the rule which seems to be in\nthere, I likely still wouldn't have understood _why_ that rule works\nor is needed; it would just have been some black box.\n\n> > Also, if this explanation is aimed at newcomers, then saying only\n> > \"doing A..F will retrieve 5 commits\" without actually saying _which_\n> > commits those are is perhaps not so helpful.\n>\n> It doesn't matter which specific commits are retrieved, the only thing\n> that matters is that `X op Y` is not additive.\n\nThe very first question which popped into my head upon reading \"Doing\nA..F will retrieve 5 commits\" was \"which five commits?\". Not being\ntold the answer by the text did not help me feel confident that I knew\nthe correct five commits. Had the text stated explicitly \"the five\ncommits B, C, D, E, F\", then there would be no question and no feeling\nof uncertainty about it. So, whatever precision your above statement\nmight have, it is likely to be lost on the general newcomer who is\nsimply trying to learn about and understand Git revisions.\n"},{"id":"427239","messageId":"60c62eaa7d538_41f4520899@natae.notmuch","threadId":"55912","inReplyTo":"CAPig+cQhve3pTdrm8ZeJ8-YPJj4gWrk=BB9rLqRojXgYJrAi2Q@mail.gmail.com","subject":"Re: [PATCH] doc: revisions: improve single range explanation","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2021-06-13T16:13:30Z","receivedAt":"2021-06-13T16:14:45Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Eric Sunshine wrote:\n> On Sun, Jun 13, 2021 at 12:26 AM Felipe Contreras\n> <felipe.contreras@gmail.com> wrote:\n> > Eric Sunshine wrote:\n> > > For what it's worth, as a person who is far from expert at revision\n> > > ranges, I had to read this revised text five or six times and think\n> > > about it quite a bit to understand what it is saying,\n> >\n> > Can you explain why?\n> \n> Probably not to a degree which will satisfy you. And I'm not being\n> flippant by saying that. I mean only that it is more than a little\n> difficult to explain why one thing \"clicks\" easily in the brain while\n> something else doesn't. I can only relate (to some extent) what I\n> experienced while reading your revised text.\n\nYes, but the documentation is not for you, it's for the majority of\nusers, so it behooves to try to understand the reason to see if it\napplies to the population in general.\n\n> > This is the context: commands don't generally take two ranges:\n> >\n> >  1. Unless otherwise noted, all git commands that operate on a set of\n> >     commits work on a single revision range.\n> >\n> >  2. Doing A..F will retrieve 5 commits, and doing B..E will retrieve 3\n> >     commits, but doing A..F B..E will not retrieve two revision ranges\n> >     totalling 8 commits.\n> >\n> > At this point what isn't clear? Isn't it clear that `A..F B..E` aren't\n> > two revision ranges?\n> \n> The documentation stating explicitly that `A..F B..E` is not two\n> ranges is fine. What was difficult to understand was your explanation\n> of _why_ those are not two ranges.\n\nAt this point the _why_ has not been explained, merely that these two\nthings don't result in two ranges.\n\n> >  3. Instead the starting point A gets overridden by B, and the ending\n> >     point of E by F, effectively becoming B..F, a single revision range.\n> >\n> > What isn't clear about that? A gets superseded by B because it's higher\n> > in the graph. And if you do `git log D E F` it's clear that doing\n> > `git log F` will get you the same thing, isn't it?\n> \n> One of the reasons I had to re-read your text so many times was\n> because it was difficult to build a mental model of what you were\n> saying, and to follow along with all the \"this replaces that\" and\n> \"this other thing replaces that other thing\". While doing so, I\n> repeatedly had to glance back at the original `A..F B..E` to make sure\n> the mental model I was building was correct or still made sense.\n\nI wonder why that is the case. A..F is so simple it doesn't have to be\nexplained, Ruby even expands that obvious range.\n\n  ---A---B---C---D---E---F\n     ^                   ^\n    from                 to\n\nAnd B..E:\n\n  ---A---B---C---D---E---F\n         ^           ^\n        from         to\n\nIn Ruby the range can be defined simply as: 'A'..'F'\n\n  [\"A\", \"B\", \"C\", \"D\", \"E\", \"F\"]\n\nWould 1..6 be easier to picture?\n\n> The word \"overridden\" didn't help because I couldn't tell if, by\n> \"overridden\", you meant that something got replaced by something else\n> or if something was merely ignored. (Or maybe those are the same thing\n> in this case, but how will a newcomer -- who is trying to learn this\n> from scratch -- know which it is?)\n\nIf I say Lucy is available from 1 to 6 p.m. and Michael from 2 to 5 p.m.\nwhy would 2 p.m supersede 1 p.m.?\n\nIf we are trying to define a starting point, obviously the latest\nstarting point is the one that wins. No?\n\n> However, an even bigger problem I experienced while reading your\n> revised text is that it felt like it was trying to express some rule\n> which the reader should internalize (\"replace this with that, and\n> replace this other thing too\")\n\nThe text starts with *for example*. Therefore it's not something\ngeneral, it's an example.\n\n> Junio's explanation, on the other hand, was simple and to the point,\n> and (for whatever reason) clicked easily in my brain, such that I came\n> away feeling that I could apply the knowledge immediately to other\n> situations.\n\nJunio's explanation is inaccurate because it stated that this:\n\n Unless otherwise noted, all git commands that operate on a set of\n commits work on a single revision range.\n\nIs the same as this:\n\n writing two \"two-dot range notation\" next to each does *not* specify\n two revision ranges for most commands.\n\nBut it is not the same.\n\nCan you tell me why?\n\n> On the other hand, after reading your proposed text, I did not feel as\n> if I had gained any knowledge, and even had I picked up the rule which\n> seems to be in there,\n\nThe text never mentioned any rule.\n\n> > > Also, if this explanation is aimed at newcomers, then saying only\n> > > \"doing A..F will retrieve 5 commits\" without actually saying _which_\n> > > commits those are is perhaps not so helpful.\n> >\n> > It doesn't matter which specific commits are retrieved, the only thing\n> > that matters is that `X op Y` is not additive.\n> \n> The very first question which popped into my head upon reading \"Doing\n> A..F will retrieve 5 commits\" was \"which five commits?\".\n\nKeep reading.\n\n> So, whatever precision your above statement might have, it is likely\n> to be lost on the general newcomer who is simply trying to learn about\n> and understand Git revisions.\n\nOr maybe it's something that only applies to you.\n\nCheers.\n\n-- \nFelipe Contreras\n"},{"id":"427242","messageId":"60c63bc3f616_41f452086b@natae.notmuch","threadId":"55912","inReplyTo":"CABPp-BE4r=Nhw2sJS++7Eh1K5rpyWgg+f8vDTf92JBayt1B_cA@mail.gmail.com","subject":"Re: [PATCH] doc: revisions: improve single range explanation","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2021-06-13T17:09:23Z","receivedAt":"2021-06-13T17:10:42Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Elijah Newren wrote:\n> On Sat, Jun 12, 2021 at 9:25 PM Felipe Contreras\n> <felipe.contreras@gmail.com> wrote:\n> >\n> > Eric Sunshine wrote:\n> > > On Sat, Jun 12, 2021 at 8:44 PM Felipe Contreras\n> > > <felipe.contreras@gmail.com> wrote:\n> > > > The original explanation didn't seem clear enough to some people.\n> > > >\n> > > > Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n> > > > ---\n> > > > diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt\n> > > > @@ -299,22 +299,22 @@ empty range that is both reachable and unreachable from HEAD.\n> > > > +For example, if you have a linear history like this:\n> > > >\n> > > > +    ---A---B---C---D---E---F\n> > > >\n> > > > +Doing A..F will retrieve 5 commits, and doing B..E will retrieve 3\n> > > > +commits, but doing A..F B..E will not retrieve two revision ranges\n> > > > +totalling 8 commits. Instead the starting point A gets overriden by B,\n> > > > +and the ending point of E by F, effectively becoming B..F, a single\n> > > > +revision range.\n> > >\n> > > s/overriden/overridden/\n> > >\n> > > For what it's worth, as a person who is far from expert at revision\n> > > ranges, I had to read this revised text five or six times and think\n> > > about it quite a bit to understand what it is saying,\n> >\n> > Can you explain why?\n> \n> I tend to agree with Eric.  I think the example you chose is likely to\n> be misinterpreted and your wording magnifies it.  A..F B..E simplifies\n> to B..F which is *almost* the union of A..F and B..E, it's only\n> missing A.  Off-by-one errors are easy to miss.\n\nYes, but right before it's explained that the ending point is F.\nNot E, F.\n\n> You make it more likely that they'll miss it, because there are only 6\n> commits total in the union, and you are trying to explain why listing\n> A..F B..E while not be 8 commits, which readers can easily respond\n> with, \"Well, of course it's not 8 commits.  There's only 6.\n\nIf the reader understands that no more than 6 commits can be returned,\nthen the reader has understood the point that the operation is not\naddition.\n\n> When you do the union operation, of course the duplicates go away\",\n> and miss the actual point that A got excluded.\n\nBut that is not the point. This is the point:\n\n  Unless otherwise noted, all git commands that operate on a set of\n  commits work on a single revision range.\n\nYou are missing the forest for the trees.\n\nIn the context of gitrevisions(7) the user has just been told that:\n\n  1. We are trying to specify a graph of commits reachable from a\n     commit, or commits.\n\nThe user was shown this graph:\n\n  G   H   I   J\n   \\ /     \\ /\n    D   E   F\n     \\  |  / \\\n      \\ | /   |\n       \\|/    |\n        B     C\n         \\   /\n          \\ /\n           A\n\nAnd that B is A^, therefore doing `git log A B` is redundant, as is\ndoing `git log A B D`.\n\n  2. The caret notation `^r1 r2` means commits reachable from r2, but\n     exclude commits reachable from r1 (r1 and it's ancestors)\n\nThat means '^D A' will exclude D G and H.\n\n  3. The two-dot range notation `r1..r2` is the same as `^r1 r2`\n\n\nNow, whith this context in mind, we are trying to hedge the corner-case\nof `r1..r2 r3..r4` in other words: `^r1 r2 ^r3 r4`.\n\nThe user has been told already that C..A is the same as `^C A` (I'm\nchanging the order to be consistent with the graph above). And to make\nmy point clear I actually don't need two starting points.\n\nSo how about this:\n\n  Commands that are specifically designed to take two distinct ranges\n  (e.g. \"git range-diff R1 R2\" to compare two ranges) do exist, but\n  they are exceptions.  Unless otherwise noted, all git commands\n  that operate on a set of commits work on a single revision range. Just\n  like 'A A' coalesces to 'A', 'B..A C..A' is the same as the\n  single revision range '^B ^C A'.\n\n-- \nFelipe Contreras\n"},{"id":"427353","messageId":"CABPp-BHh9dfuOV3wM_K7Zks4hzry3RDxjsaxrLztLDy0FtELCA@mail.gmail.com","threadId":"55912","inReplyTo":"60c63bc3f616_41f452086b@natae.notmuch","subject":"Re: [PATCH] doc: revisions: improve single range explanation","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2021-06-14T14:39:58Z","receivedAt":"2021-06-14T14:41:27Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Sun, Jun 13, 2021 at 10:09 AM Felipe Contreras\n<felipe.contreras@gmail.com> wrote:\n>\n> Elijah Newren wrote:\n> > On Sat, Jun 12, 2021 at 9:25 PM Felipe Contreras\n> > <felipe.contreras@gmail.com> wrote:\n> > >\n> > > Eric Sunshine wrote:\n> > > > On Sat, Jun 12, 2021 at 8:44 PM Felipe Contreras\n> > > > <felipe.contreras@gmail.com> wrote:\n> > > > > The original explanation didn't seem clear enough to some people.\n> > > > >\n> > > > > Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n> > > > > ---\n> > > > > diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt\n> > > > > @@ -299,22 +299,22 @@ empty range that is both reachable and unreachable from HEAD.\n> > > > > +For example, if you have a linear history like this:\n> > > > >\n> > > > > +    ---A---B---C---D---E---F\n> > > > >\n> > > > > +Doing A..F will retrieve 5 commits, and doing B..E will retrieve 3\n> > > > > +commits, but doing A..F B..E will not retrieve two revision ranges\n> > > > > +totalling 8 commits. Instead the starting point A gets overriden by B,\n> > > > > +and the ending point of E by F, effectively becoming B..F, a single\n> > > > > +revision range.\n> > > >\n> > > > s/overriden/overridden/\n> > > >\n> > > > For what it's worth, as a person who is far from expert at revision\n> > > > ranges, I had to read this revised text five or six times and think\n> > > > about it quite a bit to understand what it is saying,\n> > >\n> > > Can you explain why?\n> >\n> > I tend to agree with Eric.  I think the example you chose is likely to\n> > be misinterpreted and your wording magnifies it.  A..F B..E simplifies\n> > to B..F which is *almost* the union of A..F and B..E, it's only\n> > missing A.  Off-by-one errors are easy to miss.\n>\n> Yes, but right before it's explained that the ending point is F.\n> Not E, F.\n\nI think this is somewhat of a useless distinction -- not for the end\nresult, but in terms of helping users understand.  We started adding\nan explanation to the manual because users misunderstand how\n\"start1..end1 start2..end2\" is treated and we want to correct their\nmisunderstandings.  In that context, the only misunderstanding I can\nthink of that is dispelled by specifying F is the endpoint would be\n\"two ranges are intersected to get the range of commits that log will\noperate on\".  I've never seen users assume that or make such a\nmistake.  I've always seen them assume that the \"two ranges are\ncombined with a union\".  In that case, F matches their\nmisunderstanding, so this part of the explanation does nothing to help\ncorrect their assumptions.\n\nThe only place their misunderstanding disagrees with the correct\nanswer for your example is on the other side of those ranges.  They\nwould have gotten an incorrect answer of \"A..F B..E\" == \"A..F\" ,\nwhereas the correct answer is \"B..F\".  That's an off-by-one error, but\nI think they're likely to miss it.  Especially given that folks\nalready mess up the left hand side of single \"FOO..BAR\" expressions\nwith off-by-one errors.\n\n> > You make it more likely that they'll miss it, because there are only 6\n> > commits total in the union, and you are trying to explain why listing\n> > A..F B..E while not be 8 commits, which readers can easily respond\n> > with, \"Well, of course it's not 8 commits.  There's only 6.\n>\n> If the reader understands that no more than 6 commits can be returned,\n> then the reader has understood the point that the operation is not\n> addition.\n\nWho in the world ever assumes that \"two dotted ranges are combined via\nlist addition\"?  I've only ever come across users assuming the\noperation is a union (or, equivalently, addition on sets).  I don't\nunderstand why you even try to make that point, and think it's a\ndistraction that does more harm than good.\n\n> > When you do the union operation, of course the duplicates go away\",\n> > and miss the actual point that A got excluded.\n>\n> But that is not the point. This is the point:\n>\n>   Unless otherwise noted, all git commands that operate on a set of\n>   commits work on a single revision range.\n>\n> You are missing the forest for the trees.\n\nI think you are missing the boat.\n\nThat sentence on its own is completely insufficient to dispel the\nmisunderstanding.  All that sentence says to users is that if they\nspecify what they think of as \"two ranges\" that we'll somehow treat it\nas one; but since users are prone to think that \"revision range\" is\ninterchangeable with \"set of revisions\" (especially since we defined\nA..B elsewhere in set operations), this will merely make them think in\nterms of what set operation they need to perform on the \"two ranges\"\nto get the set of commits the operation will function on.\n\nMost users I've seen simply do that via applying a simple operation to\ncombine two ranges into one.  Everyone I've ever run across that\nmisunderstands this \"two range\" thing, does so in the same way: by\nassuming that the two ranges are combined via a union to get an\ninteresting set of commits.\n\nThe example you provide should attempt to help explain why that mental\nmodel is mistaken and provide them with a corrected one.  Your\nresponse to Eric suggests you're not even trying to provide a\ncorrected mental model, and your response here suggests you are trying\nto only correct mistakes of the form \"take two revision ranges and add\nthem keeping duplicates\" and \"take two revision ranges and intersect\nthem\", neither of which I've observed in the wild.\n\n> In the context of gitrevisions(7) the user has just been told that:\n>\n>   1. We are trying to specify a graph of commits reachable from a\n>      commit, or commits.\n>\n> The user was shown this graph:\n>\n>   G   H   I   J\n>    \\ /     \\ /\n>     D   E   F\n>      \\  |  / \\\n>       \\ | /   |\n>        \\|/    |\n>         B     C\n>          \\   /\n>           \\ /\n>            A\n>\n> And that B is A^, therefore doing `git log A B` is redundant, as is\n> doing `git log A B D`.\n>\n>   2. The caret notation `^r1 r2` means commits reachable from r2, but\n>      exclude commits reachable from r1 (r1 and it's ancestors)\n>\n> That means '^D A' will exclude D G and H.\n>\n>   3. The two-dot range notation `r1..r2` is the same as `^r1 r2`\n>\n>\n> Now, whith this context in mind, we are trying to hedge the corner-case\n> of `r1..r2 r3..r4` in other words: `^r1 r2 ^r3 r4`.\n>\n> The user has been told already that C..A is the same as `^C A` (I'm\n> changing the order to be consistent with the graph above). And to make\n> my point clear I actually don't need two starting points.\n>\n> So how about this:\n>\n>   Commands that are specifically designed to take two distinct ranges\n>   (e.g. \"git range-diff R1 R2\" to compare two ranges) do exist, but\n>   they are exceptions.  Unless otherwise noted, all git commands\n>   that operate on a set of commits work on a single revision range. Just\n>   like 'A A' coalesces to 'A', 'B..A C..A' is the same as the\n>   single revision range '^B ^C A'.\n\nYour example here almost seems to suggest that we do an intersection\nof the \"two ranges\" to get the answer.  It's certainly not your\nintent, but I think the users I've helped would be prone to read it\nthat way due to your focus on coalescing, and due to your selection of\nan example which happens to give the correct answer when using the\nintersection misinterpretation.\n\nI would be much happier with something like this:\n\n\"\"\"\nNote: There is no shorthand for getting a union or intersection of\nmultiple dotted ranges.\n\nCommands that are specifically designed to take two distinct ranges\n(e.g. \"git range-diff R1 R2\" to compare two ranges) do exist, but they\nare exceptions.  Unless otherwise noted, all git commands that operate\non a set of commits work on a single revision range.  Thus, just as\n\"A..B\" translates to \"^A B\", the expression \"A..B C..D\" translates to\n\"^A B ^C D\", i.e. all commits reachable from either B or D, as long as\nthey are not reachable from either A or C.  This is much different\nthan you would get by trying to do either an intersection or union of\nthe two separate ranges A..B and C..D.  Compare the differences on the\nfollowing simple linear history:\n\n    ---A---B---C---D---E---F---G---H\n\nThe command\n\n$ git log A..E C..H\n\nwould be the same as\n\n$ git log C..H\n\n(since E is reachable from H, and A is reachable from C).  In contrast,\nthe union of A..E and C..H would be A..H, while the intersection would\nbe C..E.\n\"\"\"\n"},{"id":"427455","messageId":"60c894c1daaed_e633208cb@natae.notmuch","threadId":"55912","inReplyTo":"CABPp-BHh9dfuOV3wM_K7Zks4hzry3RDxjsaxrLztLDy0FtELCA@mail.gmail.com","subject":"Re: [PATCH] doc: revisions: improve single range explanation","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2021-06-15T11:53:37Z","receivedAt":"2021-06-15T11:53:45Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Elijah Newren wrote:\n> On Sun, Jun 13, 2021 at 10:09 AM Felipe Contreras\n> <felipe.contreras@gmail.com> wrote:\n> > Elijah Newren wrote:\n\n> > > I tend to agree with Eric.  I think the example you chose is likely to\n> > > be misinterpreted and your wording magnifies it.  A..F B..E simplifies\n> > > to B..F which is *almost* the union of A..F and B..E, it's only\n> > > missing A.  Off-by-one errors are easy to miss.\n> >\n> > Yes, but right before it's explained that the ending point is F.\n> > Not E, F.\n> \n> I think this is somewhat of a useless distinction -- not for the end\n> result, but in terms of helping users understand.  We started adding\n> an explanation to the manual because users misunderstand how\n> \"start1..end1 start2..end2\" is treated and we want to correct their\n> misunderstandings.  In that context, the only misunderstanding I can\n> think of that is dispelled by specifying F is the endpoint would be\n> \"two ranges are intersected to get the range of commits that log will\n> operate on\".  I've never seen users assume that or make such a\n> mistake.  I've always seen them assume that the \"two ranges are\n> combined with a union\".\n\nThen that warrants yet another paragraph, because this one is for:\n\n  Commands that are specifically designed to take two distinct ranges\n  (e.g. \"git range-diff R1 R2\" to compare two ranges) do exist, but they\n  are exceptions.\n\nProbably outside the section of Dotted Range Notations, because if the\nuser is confused about what 'C B A A' should do, that has nothing to do\nwith this dotted ranges.\n\nMaybe after the user has been told that:\n\n  Specifying several revisions means the set of commits reachable from\n  any of the given commits.\n\n  A commit's reachable set is the commit itself and the commits in\n  its ancestry chain.\n\n> > > You make it more likely that they'll miss it, because there are only 6\n> > > commits total in the union, and you are trying to explain why listing\n> > > A..F B..E while not be 8 commits, which readers can easily respond\n> > > with, \"Well, of course it's not 8 commits.  There's only 6.\n> >\n> > If the reader understands that no more than 6 commits can be returned,\n> > then the reader has understood the point that the operation is not\n> > addition.\n> \n> Who in the world ever assumes that \"two dotted ranges are combined via\n> list addition\"?\n\nI don't know, but that is the paragraph we are on:\n\n  Commands that are specifically designed to take two distinct ranges\n  (e.g. \"git range-diff R1 R2\" to compare two ranges) do exist, but they\n  are exceptions.\n\nIf you are arguing for the removal of this entire paragraph and its\nexamples, I'd be fine with that.\n\n> I've only ever come across users assuming the\n> operation is a union (or, equivalently, addition on sets).  I don't\n> understand why you even try to make that point, and think it's a\n> distraction that does more harm than good.\n\nIf you think it's impossible for the user to assume two dotted ranges\nmeans addition, please explain what is the point of this sentence:\n\n  Unless otherwise noted, all \"git\" commands that operate on a set of\n  commits work on a single revision range.\n\n> > > When you do the union operation, of course the duplicates go away\",\n> > > and miss the actual point that A got excluded.\n> >\n> > But that is not the point. This is the point:\n> >\n> >   Unless otherwise noted, all git commands that operate on a set of\n> >   commits work on a single revision range.\n> >\n> > You are missing the forest for the trees.\n> \n> I think you are missing the boat.\n> \n> That sentence on its own is completely insufficient to dispel the\n> misunderstanding.\n\nOne misunderstanding, perhaps, not the one we are trying to tackle\nhere.\n\n> All that sentence says to users is that if they specify what they\n> think of as \"two ranges\" that we'll somehow treat it as one;\n\nDidn't you just said the user would never think it's actually two\nranges?\n\nWhat's the point in saying that if the user already knows it?\n\n> but since users are prone to think that \"revision range\" is\n> interchangeable with \"set of revisions\" (especially since we defined\n> A..B elsewhere in set operations), this will merely make them think in\n> terms of what set operation they need to perform on the \"two ranges\"\n> to get the set of commits the operation will function on.\n\nThat belongs in a separate paragraph.\n\n> The example you provide should attempt to help explain why that mental\n> model is mistaken and provide them with a corrected one.  Your\n> response to Eric suggests you're not even trying to provide a\n> corrected mental model, and your response here suggests you are trying\n> to only correct mistakes of the form \"take two revision ranges and add\n> them keeping duplicates\" and \"take two revision ranges and intersect\n> them\", neither of which I've observed in the wild.\n\nI'm providing an example for the paragraph that is already written.\n\nIf you want me to rewrite the entire section I can certainly give it a\ntry.\n\n\n> Commands that are specifically designed to take two distinct ranges\n> (e.g. \"git range-diff R1 R2\" to compare two ranges) do exist, but they\n> are exceptions.  Unless otherwise noted, all git commands that operate\n> on a set of commits work on a single revision range.\n\nIsn't this obvious for all users?\n\n> Thus, just as \"A..B\" translates to \"^A B\", the expression \"A..B C..D\"\n> translates to \"^A B ^C D\", i.e. all commits reachable from either B or\n> D, as long as they are not reachable from either A or C.\n\nHow about we remove the entire paragraph and replace it with:\n\n  When specifying two ranges, such as 'A..B C..D', the way this is\n  interpreted is as a single range '^A B ^C D', that is: all commits\n  reachable from either B or D, as long as they are not reachable from\n  either A or C. Assuming a linear history, B would be reachable from C,\n  so this is the same as '^C D'.\n\n-- \nFelipe Contreras\n"}]}