diff mbox series

Mismatch meaning between git-diff and git-log for the .. (double dot notation) and ... (triple dot notation)

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

Commit Message

Arnaud Bertrand Dec. 23, 2019, 12:51 p.m. UTC
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

Comments

Junio C Hamano Dec. 23, 2019, 6:02 p.m. UTC | #1
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.
Kevin Daudt Dec. 23, 2019, 6:29 p.m. UTC | #2
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
Jonathan Nieder Dec. 23, 2019, 9:59 p.m. UTC | #3
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
Junio C Hamano Dec. 23, 2019, 10:10 p.m. UTC | #4
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 mbox series

Patch

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