Message ID | CAEW0o+gYqWT5u-Tf8aDoMgXaf36Mb-XOApLNs4D+GMVLvsOjxg@mail.gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Mismatch meaning between git-diff and git-log for the .. (double dot notation) and ... (triple dot notation) | expand |
Please unlearn dot-dot and three-dots when using "git diff", which is not about ranges but about comparing two endpoints. If we were reinventing Git today from scratch, we would make "git diff A..B" an error. You can consider it a bug that the command accepts a range notation, but this will not change any time soon without a large fight to find and fix uses of the syntax in scripts by longtime Git users have written over the years. Allowing dot-dot on the command line of "git diff", instead of diagnosing them as errors and dying, was a stupid mistake we (well, mostly Linus, but I am willing to take the blame too) made due to laziness when we reused the machinery, which we invented to parse the command line of "log" family of commands to specify ranges, to parse the command line of "diff", which accidentally ended up allowing the syntax for ranges where it shouldn't be allowed. And worse yet, since there was only dot-dot and three-dots came much later, "git diff A..B" ended up comparing the endpoints A and B, because there didn't even A...B notation exist. This is not limited to you but any user of modern Git is better off to pretend "git diff A..B" does not exist; please unlearn dot-dot and three-dots when using "git diff" and you'd be happier.
On Mon, Dec 23, 2019 at 10:02:31AM -0800, Junio C Hamano wrote: > Please unlearn dot-dot and three-dots when using "git diff", which > is not about ranges but about comparing two endpoints. If we were > reinventing Git today from scratch, we would make "git diff A..B" an > error. You can consider it a bug that the command accepts a range > notation, but this will not change any time soon without a large > fight to find and fix uses of the syntax in scripts by longtime Git > users have written over the years. > > Allowing dot-dot on the command line of "git diff", instead of > diagnosing them as errors and dying, was a stupid mistake we (well, > mostly Linus, but I am willing to take the blame too) made due to > laziness when we reused the machinery, which we invented to parse > the command line of "log" family of commands to specify ranges, to > parse the command line of "diff", which accidentally ended up > allowing the syntax for ranges where it shouldn't be allowed. > > And worse yet, since there was only dot-dot and three-dots came much > later, "git diff A..B" ended up comparing the endpoints A and B, > because there didn't even A...B notation exist. > > This is not limited to you but any user of modern Git is better off > to pretend "git diff A..B" does not exist; please unlearn dot-dot > and three-dots when using "git diff" and you'd be happier. I agreen that you should not use `A..B`, but what is wrong with `A...B`? The alternative is a lot more verbose. git diff $(git merge-base A B) B Kevin
Kevin Daudt wrote: > On Mon, Dec 23, 2019 at 10:02:31AM -0800, Junio C Hamano wrote: >> Please unlearn dot-dot and three-dots when using "git diff", which >> is not about ranges but about comparing two endpoints. If we were >> reinventing Git today from scratch, we would make "git diff A..B" an >> error. You can consider it a bug that the command accepts a range >> notation, but this will not change any time soon without a large >> fight to find and fix uses of the syntax in scripts by longtime Git >> users have written over the years. [...] > I agree that you should not use `A..B`, but what is wrong with > `A...B`? The alternative is a lot more verbose. > > git diff $(git merge-base A B) B Commands like "git checkout" have been learning a `...` shorthand which is not much better as far as intuitiveness goes: # doesn't work, just here for demonstration git diff A...B B With hindsight, "git diff A..B" would be the perfect spelling for this, but that would break too many people's muscle memories and scripts. Would it make sense to have a commandline option for this? # doesn't work, just here for demonstration git diff --fork-point A B A random thought, Jonathan
Kevin Daudt <kdaudt@alpinelinux.org> writes: >> This is not limited to you but any user of modern Git is better off >> to pretend "git diff A..B" does not exist; please unlearn dot-dot >> and three-dots when using "git diff" and you'd be happier. > > I agreen that you should not use `A..B`, but what is wrong with > `A...B`? The alternative is a lot more verbose. > > git diff $(git merge-base A B) B Because it would interfere with even grander consistency that we could achieve in the future, if we get rid of it. Within the context of "git diff" (but not "git" in general), "git diff A...B" that expands to "git diff $(git merge-base A B) B" may appear OK, but this thread started by comparing "git log" and "git diff", so it is no longer worth limiting our vision to a single "git diff" command if we want to continue this thread. Some commands, like "git checkout A...B", know that A...B can stand for "git merge-base A B" in a context that does not call for a range but calls for a single revision. We probably would want to teach it the general revision parser machinery so that this can consistently be used. In such a world, "git diff A...B" ought to mean, because "diff" is about discrete endpoints and not about ranges, "git diff $(git merge-base A B)", i.e. it should behave just like "git diff C" that compares the given single commit and the contents in the working tree through the index. "git diff A...B" we currently have by mistake should be spelled in "git diff A...B B" (or alternatively, "git diff B...A B"). It would take a long time and careful transition planninng to reach there, and training people not to use dot-dot notation is merely a very small first step, though.
diff --git a/foo b/foo index 30e1159..2570fa8 100644 --- a/foo +++ b/foo @@ -1 +1,2 @@ common +right part As expected, only the right part appears. and now with the log: $ git log --oneline --left-right L...R > f2f11c4 (tag: R) R: add a right part < 7f4f3d6 (tag: L) L: add a left part The log that concers the left part appears too! ################################################################## If now we consider the .. (double dots notation), it is exactly the opposite! $ git diff L..R -- foo diff --git a/foo b/foo index 6f2cf25..2570fa8 100644 --- a/foo +++ b/foo @@ -1,2 +1,2 @@ common -LeftPart +right part
Hello, Git Version 2.24.0.windows.2 Summary: triple dots git diff L...R -- foo <=> diff between CommonAncestror(L,R) to R git log L...R <=> all commit from L to R double dots git diff L..R -- foo <=> diff between L and R git log L..R <=> commit from CommonAncestror(L,R) to R So, to make the command related to the common ancestor, git diff uses the triple dots notation by opposite to git log that uses the double dots notation In details ------------ ####################################################### The ... (triple dots notation) In the diff context, the triple dots notation is related to the common ancestror: git diff L...R -- foo means diff between (common ancestor of L and R) and R is equivalent to: git diff $(git merge-base L R) R -- foo But now, if I use the same notation for git log, it means all the commit that differ from L to R Example, you can execute the following lines: mkdir test cd test git init echo common > foo git add foo git ci -m "add common part" git switch -c L echo LeftPart >> foo git ci -am "add a left part" git switch master git switch -c R echo "right part" >> foo git ci -am "add a right part" git switch master git diff L...R -- foo And verify: $ git diff L...R -- foo It is clear that both branches differences appear and with git log: $ git log --oneline --left-right L..R > f2f11c4 (tag: R) R: add a right part For the log, only the commit from the common ancestror to R appear ! So there is well an incoherence between diff and log using the multi-dots notation Best regards, Arnaud Bertrand