All of lore.kernel.org
 help / color / mirror / Atom feed
* generating combined diff without an existing merge commit
@ 2016-10-21 21:40 Jacob Keller
  2016-10-21 22:01 ` Jacob Keller
  0 siblings, 1 reply; 8+ messages in thread
From: Jacob Keller @ 2016-10-21 21:40 UTC (permalink / raw)
  To: Git mailing list

Hi,

I recently determined that I can produce an interdiff for a series
that handles rebasing nicely and shows the conflicts resolved when
rebasing plus any other changes.

The basic idea is something like the following, assuming that v1 is a
tag that points to the first version, v2 is a tag that points to the
rebased new version, and base is a tag that points to the new base of
the series (ie: the upstream if the v2 is on a branch and has been
fully rebased)

git checkout v1
git merge base
#perform any further edits to get everything looking like v2
git commit
git show -cc HEAD

This is also equivalent to the following without having to actually do
the merge manually:

git commit-tree v2^{head} -p v1 -p master -m "some merge message"
git show <output from the commit tree above)

this nicely shows us the combined diff format which correctly shows
any conflicts required to fix up during the rebase (which we already
did because we have v2) and it also shows any *other* changes caused
by v2 but without showing changes which we didn't actually make. (I
think?)

The result is that we can nicely see what was required to produce v2
from v1 but without being cluttered by what changed in base.

However, I have to actually generate the commit to do this. I am
wondering if it is possible today to actually just do something like:

git diff <treeish> <treeish> <treeish> and get the result that I want?

I've already started digging to see if I can do that but haven't found
anything yet.

Thanks,
Jake

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: generating combined diff without an existing merge commit
  2016-10-21 21:40 generating combined diff without an existing merge commit Jacob Keller
@ 2016-10-21 22:01 ` Jacob Keller
  2016-10-21 22:41   ` Junio C Hamano
  0 siblings, 1 reply; 8+ messages in thread
From: Jacob Keller @ 2016-10-21 22:01 UTC (permalink / raw)
  To: Git mailing list

On Fri, Oct 21, 2016 at 2:40 PM, Jacob Keller <jacob.keller@gmail.com> wrote:
> Hi,
>
> I recently determined that I can produce an interdiff for a series
> that handles rebasing nicely and shows the conflicts resolved when
> rebasing plus any other changes.
>
> The basic idea is something like the following, assuming that v1 is a
> tag that points to the first version, v2 is a tag that points to the
> rebased new version, and base is a tag that points to the new base of
> the series (ie: the upstream if the v2 is on a branch and has been
> fully rebased)
>
> git checkout v1
> git merge base
> #perform any further edits to get everything looking like v2
> git commit
> git show -cc HEAD
>
> This is also equivalent to the following without having to actually do
> the merge manually:
>
> git commit-tree v2^{head} -p v1 -p master -m "some merge message"
> git show <output from the commit tree above)
>
> this nicely shows us the combined diff format which correctly shows
> any conflicts required to fix up during the rebase (which we already
> did because we have v2) and it also shows any *other* changes caused
> by v2 but without showing changes which we didn't actually make. (I
> think?)
>
> The result is that we can nicely see what was required to produce v2
> from v1 but without being cluttered by what changed in base.
>
> However, I have to actually generate the commit to do this. I am
> wondering if it is possible today to actually just do something like:
>
> git diff <treeish> <treeish> <treeish> and get the result that I want?
>
> I've already started digging to see if I can do that but haven't found
> anything yet.
>
> Thanks,
> Jake

Turns out that somehow I must have messed up my command because "git
diff <treeish> <treeish> <treeish>" does indeed do exactly what I
want.

Thanks,
Jake

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: generating combined diff without an existing merge commit
  2016-10-21 22:01 ` Jacob Keller
@ 2016-10-21 22:41   ` Junio C Hamano
  2016-10-21 22:54     ` Jacob Keller
  0 siblings, 1 reply; 8+ messages in thread
From: Junio C Hamano @ 2016-10-21 22:41 UTC (permalink / raw)
  To: Jacob Keller; +Cc: Git mailing list

Jacob Keller <jacob.keller@gmail.com> writes:

> Turns out that somehow I must have messed up my command because "git
> diff <treeish> <treeish> <treeish>" does indeed do exactly what I
> want.

Thanks.  I was wondering why it didn't work for you, as the feature
was done exactly to support that use case ;-)

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: generating combined diff without an existing merge commit
  2016-10-21 22:41   ` Junio C Hamano
@ 2016-10-21 22:54     ` Jacob Keller
  2016-10-26  9:11       ` [PATCH] Documentation/git-diff: document git diff with 3+ commits Michael J Gruber
  0 siblings, 1 reply; 8+ messages in thread
From: Jacob Keller @ 2016-10-21 22:54 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git mailing list

On Fri, Oct 21, 2016 at 3:41 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Jacob Keller <jacob.keller@gmail.com> writes:
>
>> Turns out that somehow I must have messed up my command because "git
>> diff <treeish> <treeish> <treeish>" does indeed do exactly what I
>> want.
>
> Thanks.  I was wondering why it didn't work for you, as the feature
> was done exactly to support that use case ;-)

I'm not really sure. It kept spitting out usage information to me, but
then I tried again with a fresh example and it worked as expected.

Thanks,
Jake

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH] Documentation/git-diff: document git diff with 3+ commits
  2016-10-21 22:54     ` Jacob Keller
@ 2016-10-26  9:11       ` Michael J Gruber
  2016-10-26 18:11         ` Junio C Hamano
  0 siblings, 1 reply; 8+ messages in thread
From: Michael J Gruber @ 2016-10-26  9:11 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jacob Keller

That one is difficult to discover but super useful, so document it:
Specifying 3 or more commits makes git diff switch to combined diff.

Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
---

Notes:
    Note that we have the following now:
    
    'git diff A B' displays 'B minus A'
    'git diff A B C' displays 'A minus B' and 'A minus C'
    
    While I know why, that (the implicit '-R' seems unfortunate).
    
    (NB: One has to use '-c' if A is an actual merge commiti, it seems.)
    
    If M is a merge base for A and B, we have:
    
    'git diff A..B' equivalent to 'git diff A B'
    in contrast to 'git log A..B' listing commits between M and B only
    (without the commits between M and A unless they are "in" B).
    
    I would expect 'git diff M B' here.
    
    'git diff A...B' is equivalent to 'git diff M B'
    in contrast to 'git log A...B' listing commits between M and A (marked left)
    as well as commits between M and B (marked right).
    
    I would expect 'git diff -c -R M A B' here.
    
    Somehow the positive and negative ends of these ranges don't correspond well
    with thinking about diffs as differences between these ends.
    
    [I'm not exact with my use of "between" regarding boundary commits.]

 Documentation/git-diff.txt | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
index bbab35fcaf..2047318a27 100644
--- a/Documentation/git-diff.txt
+++ b/Documentation/git-diff.txt
@@ -12,6 +12,7 @@ SYNOPSIS
 'git diff' [options] [<commit>] [--] [<path>...]
 'git diff' [options] --cached [<commit>] [--] [<path>...]
 'git diff' [options] <commit> <commit> [--] [<path>...]
+'git diff' [options] <commit> <commit> <commit> [<commit>...]
 'git diff' [options] <blob> <blob>
 'git diff' [options] [--no-index] [--] <path> <path>
 
@@ -75,9 +76,16 @@ two blob objects, or changes between two files on disk.
 	"git diff $(git-merge-base A B) B".  You can omit any one
 	of <commit>, which has the same effect as using HEAD instead.
 
+'git diff' [options] <commit> <commit> <commit> [<commit>...]::
+
+	This is to view a combined diff between the first <commit>
+	and the remaining ones, just like viewing a combined diff
+	for a merge commit (see below) where the first <commit>
+	is the merge commit and the remaining ones are the parents.
+
 Just in case if you are doing something exotic, it should be
 noted that all of the <commit> in the above description, except
-in the last two forms that use ".." notations, can be any
+in the two forms that use ".." notations, can be any
 <tree>.
 
 For a more complete list of ways to spell <commit>, see
-- 
2.10.1.723.g0f00470


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] Documentation/git-diff: document git diff with 3+ commits
  2016-10-26  9:11       ` [PATCH] Documentation/git-diff: document git diff with 3+ commits Michael J Gruber
@ 2016-10-26 18:11         ` Junio C Hamano
  2016-10-27  9:27           ` Michael J Gruber
  0 siblings, 1 reply; 8+ messages in thread
From: Junio C Hamano @ 2016-10-26 18:11 UTC (permalink / raw)
  To: Michael J Gruber; +Cc: git, Jacob Keller

Michael J Gruber <git@drmicha.warpmail.net> writes:

> That one is difficult to discover but super useful, so document it:
> Specifying 3 or more commits makes git diff switch to combined diff.
>
> Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
> ---
>
> Notes:
>     Note that we have the following now:
> ...
>     'git diff A..B' equivalent to 'git diff A B'
>     in contrast to 'git log A..B' listing commits between M and B only
>     (without the commits between M and A unless they are "in" B).

The standard answer is: 

    Do not use two-dot form with 'git diff', if you find it
    confusing.  Diff is about two endpoints, not about a range
    between two.

The reason why we do not reject can be easily guessed by any
intelligent person when some historical background is given, I
think.

 - In the beginning A...B did not exist.  A..B was the only "range"
   notation.

 - "git log A..B" was in wide use.  Remember, "git log A...B" did
   not exist.

 - People started mistyping "git diff A..B", which looked as if the
   user typed "git diff ^A B" to the internal.

 - Git _could_ have rejected that as a bogus request to diff two
   points, ^A (what is that???) and B, but "What else could the user
   have meant with 'git diff A..B' other than 'git diff A B'?" was
   an argument to favor doing _something_ useful rather than
   erroring out.  Remember, "A...B" did not exist when this
   happened.

So there.  We may want to deprecate "diff A..B" but I personally do
not think it is worth the effort.  There is no substitute for the
current "diff A...B" to allow us to deprecate both at the same time,
which is the required first step if we want to eventually swap their
meaning in a far future version of Git which would have been better
if we had hindsight.  But remember, "A...B" did not exist back then. 

> diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
> index bbab35fcaf..2047318a27 100644
> --- a/Documentation/git-diff.txt
> +++ b/Documentation/git-diff.txt
> @@ -12,6 +12,7 @@ SYNOPSIS
>  'git diff' [options] [<commit>] [--] [<path>...]
>  'git diff' [options] --cached [<commit>] [--] [<path>...]
>  'git diff' [options] <commit> <commit> [--] [<path>...]
> +'git diff' [options] <commit> <commit> <commit> [<commit>...]

Made me wonder "is [<A>...] 0-or-more As or 1-or-more As?".
Don't we allow pathspecs in this case?

>  'git diff' [options] <blob> <blob>
>  'git diff' [options] [--no-index] [--] <path> <path>
>  
> @@ -75,9 +76,16 @@ two blob objects, or changes between two files on disk.
>  	"git diff $(git-merge-base A B) B".  You can omit any one
>  	of <commit>, which has the same effect as using HEAD instead.
>  
> +'git diff' [options] <commit> <commit> <commit> [<commit>...]::
> +
> +	This is to view a combined diff between the first <commit>
> +	and the remaining ones, just like viewing a combined diff
> +	for a merge commit (see below) where the first <commit>
> +	is the merge commit and the remaining ones are the parents.
> +
>  Just in case if you are doing something exotic, it should be
>  noted that all of the <commit> in the above description, except
> -in the last two forms that use ".." notations, can be any
> +in the two forms that use ".." notations, can be any
>  <tree>.
>  
>  For a more complete list of ways to spell <commit>, see

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Documentation/git-diff: document git diff with 3+ commits
  2016-10-26 18:11         ` Junio C Hamano
@ 2016-10-27  9:27           ` Michael J Gruber
  2016-10-27 18:40             ` Junio C Hamano
  0 siblings, 1 reply; 8+ messages in thread
From: Michael J Gruber @ 2016-10-27  9:27 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jacob Keller

Junio C Hamano venit, vidit, dixit 26.10.2016 20:11:
> Michael J Gruber <git@drmicha.warpmail.net> writes:
> 
>> That one is difficult to discover but super useful, so document it:
>> Specifying 3 or more commits makes git diff switch to combined diff.
>>
>> Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
>> ---
>>
>> Notes:
>>     Note that we have the following now:
>> ...
>>     'git diff A..B' equivalent to 'git diff A B'
>>     in contrast to 'git log A..B' listing commits between M and B only
>>     (without the commits between M and A unless they are "in" B).
> 
> The standard answer is: 
> 
>     Do not use two-dot form with 'git diff', if you find it
>     confusing.  Diff is about two endpoints, not about a range
>     between two.
> 
> The reason why we do not reject can be easily guessed by any
> intelligent person when some historical background is given, I
> think.

That is very well true. I'm more concerned with the presence, though,
that is: How easy to use is git now? Users choose git because they care
about the history of their project, not necessarily that of Git ;)

>  - In the beginning A...B did not exist.  A..B was the only "range"
>    notation.
> 
>  - "git log A..B" was in wide use.  Remember, "git log A...B" did
>    not exist.
> 
>  - People started mistyping "git diff A..B", which looked as if the
>    user typed "git diff ^A B" to the internal.
> 
>  - Git _could_ have rejected that as a bogus request to diff two
>    points, ^A (what is that???) and B, but "What else could the user
>    have meant with 'git diff A..B' other than 'git diff A B'?" was
>    an argument to favor doing _something_ useful rather than
>    erroring out.  Remember, "A...B" did not exist when this
>    happened.

It did not exist, but even at that point in time, "git log A..B" listed
only commits between the merge base and B, not those which are only in A
and not in B. Whereas "git diff A B" shows the differences between the
endpoints A and B.

>> @@ -12,6 +12,7 @@ SYNOPSIS
>>  'git diff' [options] [<commit>] [--] [<path>...]
>>  'git diff' [options] --cached [<commit>] [--] [<path>...]
>>  'git diff' [options] <commit> <commit> [--] [<path>...]
>> +'git diff' [options] <commit> <commit> <commit> [<commit>...]
> 
> Made me wonder "is [<A>...] 0-or-more As or 1-or-more As?".

0-or-more, at least that's the way it is used in all lines here.

> Don't we allow pathspecs in this case?

Yes, the combinded diff mode kicks in only with no blobs (not: no
pathspec, which I had misread) and N>=3 commits. Maybe I should update
the code comments in builtin/diff.c to describe this, too.

Michael

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Documentation/git-diff: document git diff with 3+ commits
  2016-10-27  9:27           ` Michael J Gruber
@ 2016-10-27 18:40             ` Junio C Hamano
  0 siblings, 0 replies; 8+ messages in thread
From: Junio C Hamano @ 2016-10-27 18:40 UTC (permalink / raw)
  To: Michael J Gruber; +Cc: git, Jacob Keller

Michael J Gruber <git@drmicha.warpmail.net> writes:

> It did not exist, but even at that point in time, "git log A..B" listed
> only commits between the merge base and B, not those which are only in A
> and not in B. Whereas "git diff A B" shows the differences between the
> endpoints A and B.

I think you are speaking with 20/20 hindsight at this point.  

Do you genuinely think you would have thought that way when there
weren't any concept of "merge-base" or "git log A...B" known to you?

>>> @@ -12,6 +12,7 @@ SYNOPSIS
>>>  'git diff' [options] [<commit>] [--] [<path>...]
>>>  'git diff' [options] --cached [<commit>] [--] [<path>...]
>>>  'git diff' [options] <commit> <commit> [--] [<path>...]
>>> +'git diff' [options] <commit> <commit> <commit> [<commit>...]
>> 
>> Made me wonder "is [<A>...] 0-or-more As or 1-or-more As?".
>
> 0-or-more, at least that's the way it is used in all lines here.
>
>> Don't we allow pathspecs in this case?
>
> Yes, the combinded diff mode kicks in only with no blobs (not: no
> pathspec, which I had misread) and N>=3 commits. Maybe I should update
> the code comments in builtin/diff.c to describe this, too.

I don't know about the code comments, but the above SYNOPSIS needs
an update, I would think.  That is why I wondered if [<A>...] were
0-or-more or 1-or-moer.

You can replace

>>>  'git diff' [options] <commit> <commit> [--] [<path>...]

with

>>>  'git diff' [options] <commit> <commit> [<commit>...] [--] [<path>...]

without adding a new line to cover the new(ly discovered) case.


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2016-10-27 18:40 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-21 21:40 generating combined diff without an existing merge commit Jacob Keller
2016-10-21 22:01 ` Jacob Keller
2016-10-21 22:41   ` Junio C Hamano
2016-10-21 22:54     ` Jacob Keller
2016-10-26  9:11       ` [PATCH] Documentation/git-diff: document git diff with 3+ commits Michael J Gruber
2016-10-26 18:11         ` Junio C Hamano
2016-10-27  9:27           ` Michael J Gruber
2016-10-27 18:40             ` Junio C Hamano

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.