threads / patch / 43501

patchRe: [PATCH] revision: add --no-full-diff command line option

Subject: Re: [PATCH] revision: add --no-full-diff command line option

## tl;dr

6 messages between Dec 20, 2006 and Dec 20, 2006. Diffs are folded; open one to read it.

replies: 5people: 2as markdown or json

Jeff King· Dec 20, 2006, 06:01 UTC · lore

[PATCH] add log.fulldiff config option

This continues to default to 'off'.
Signed-off-by: Jeff King <peff@peff.net>
---
On Tue, Dec 19, 2006 at 05:17:17PM -0800, Junio C Hamano wrote:
Show 7 quoted lines
> I typically do:
> 
>   git log --full-diff -p -SCOLLISION
> 
> The --full-diff option helps because it shows the diff for other
> files (that do not have different number of substring COLLISION
> in the pre and postimage) in the same commit as well.

I use --full-diff all the time, so this should save some typing. I can't think of a time when I wouldn't want it on, but if there is, we probably need a --no-full-diff.

Also, should this instead be diff.fulldiff?

Also also, I was going to submit a patch to document --full-diff, but I had a few questions. Should it go in diff-options? That makes some sense to me, but the parsing actually happens in setup_revisions. Furthermore, it seems to do the same thing as --pickaxe-all. Should we try to combine these?

 Documentation/config.txt |    6 ++++++
 builtin-log.c            |    6 ++++++
 2 files changed, 12 insertions(+), 0 deletions(-)
Show changes to 2 files +12 −0

Documentation/config.txt, builtin-log.c

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 22482d6..8be1fa6 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -248,6 +248,12 @@ i18n.commitEncoding::
 	browser (and possibly at other places in the future or in other
 	porcelains). See e.g. gitlink:git-mailinfo[1]. Defaults to 'utf-8'.
 
+log.fulldiff::
+	If true, log entries which have been selected through path-limiting
+	or pickaxe will show the diff for all files changed in that commit
+	instead of only the files matching the specified path or pickaxe
+	string.
+
 log.showroot::
 	If true, the initial commit will be shown as a big creation event.
 	This is equivalent to a diff against an empty tree.
diff --git a/builtin-log.c b/builtin-log.c
index 17014f7..57edd12 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -15,6 +15,7 @@
 #include <sys/time.h>
 
 static int default_show_root = 1;
+static int default_full_diff = 0;
 
 /* this is in builtin-diff.c */
 void add_head(struct rev_info *revs);
@@ -26,6 +27,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
 	rev->commit_format = CMIT_FMT_DEFAULT;
 	rev->verbose_header = 1;
 	rev->show_root_diff = default_show_root;
+	rev->full_diff = default_full_diff;
 	argc = setup_revisions(argc, argv, rev, "HEAD");
 	if (rev->diffopt.pickaxe || rev->diffopt.filter)
 		rev->always_show_header = 0;
@@ -54,6 +56,10 @@ static int git_log_config(const char *var, const char *value)
 		default_show_root = git_config_bool(var, value);
 		return 0;
 	}
+	if (!strcmp(var, "log.fulldiff")) {
+		default_full_diff = git_config_bool(var, value);
+		return 0;
+	}
 	return git_diff_ui_config(var, value);
 }
 
Junio C Hamano· Dec 20, 2006, 08:14 UTC · re: Jeff King · lore

Re: [PATCH] add log.fulldiff config option

Jeff King <peff@peff.net> writes:
> I use --full-diff all the time, so this should save some typing. I can't
> think of a time when I wouldn't want it on, but if there is, we probably
> need a --no-full-diff.
Absolutely.
> Also, should this instead be diff.fulldiff?
Probably not.
> Also also, I was going to submit a patch to document --full-diff,
> but I had a few questions. Should it go in diff-options? That makes some
> sense to me, but the parsing actually happens in setup_revisions.
Not at all.
> Furthermore, it seems to do the same thing as --pickaxe-all. Should we
> try to combine these?
No.

Try this with various combinations of with and without the two flags.

    $ git log -1 -Sstate --full-diff --pickaxe-all b3d9899 -- git-fetch.sh

Your understanding needs to be clarified on how paths are filtered, and how log family and diff interacts, and probably these need to be better documented.

First, lets forget about 'log', but talk about diff (any of diff-tree, diff-index --cached, diff-index, and diff-files). They take paths as arguments. The arguments limit the input side of the diff.

    Side note: that is why "diff -C arch/x86_64" would not
    care about renames or copies from arch/i386 to
    arch/x86_64.  The diff machinery does not even see files
    under arch/i386 with that command line.

The pickaxe (-S) is defined at the 'diff' layer, and works as the output filter from the 'diff' machinery. It omits the filepair (pair of preimage and postimage) whose both sides have the same number of specified string in them ("pickaxe criteria").

    $ git-diff-tree --name-status b3d9899

will show three paths, git-fetch.sh, git-ls-remote.sh, and pkt-line.c. But only git-fetch.sh matches the pickaxe criteria. That's why:

    $ git-diff-tree -p -Sstate b3d9899
shows only git-fetch.sh and omits the other two paths.

The option --pickaxe-all changes this paths filtering to all-or-none. If any of the incoming paths matches the pickaxe criteria, all changed paths, even the ones that do not match the criteria, are included in the output. Thus,

    $ git-diff-tree -p -Sstate --pickaxe-all b3d9899

gives three paths, although the other two paths do not change the number of string "state".

With me so far?

Now, when you give paths to commands of the log family, they are used to filter commits considered for the output by the revision traversal machinery. The revision machinery feeds only commits whose tree is different from its parents at the specified paths to the commands in the log family. b3d9899 is eligible for output in the first example because it changes "git-fetch.sh".

Then the commit is fed to the tree-diff machinery, with the same paths limiter given to the log command. If the diff machinery says there is no interesting diff, the commit is not even output.

    Side note: that is why
        $ git log -p -1 -Snosuchstring b3d9899 -- git-fetch.sh
    does not say anything.  Pickaxe says git-fetch.sh does not
    change "nosuchstring" and nothing comes out of the diff
    machinery.

What --full-diff does is to dissociate the paths limiter from the diff machinery. Before talking about pickaxe interaction, let's try one without it.

Compare:
    $ git log -p -1             b3d9899 -- git-fetch.sh
    $ git log -p -1 --full-diff b3d9899 -- git-fetch.sh

In both, git-fetch.sh is first used by the revision traversal to determine that b3d9899 is worth considering (the commit changes that path). Then the former uses the same paths limiter to compute the diff for the commit. Hence you will see only git-fetch.sh. The latter, however, does not use git-fetch.sh as the paths limiter to generate diff because of --full-diff; it feeds the full trees and that is why you can see three files.

Finally.
How do all of the above interact with the pickaxe?
    $ git log -p -1 -Sstate b3d9899 -- git-fetch.sh

Because git-fetch.sh is changed by b3d9899, revision traversal makes the commit eligible. It feeds that single path to diff machinery and pickaxe says it changes "state". Then it outputs that path.

How about this one?
    $ git log -p -1 -Sstate --full-diff b3d9899 -- git-fetch.sh

git-fetch.sh makes b3d9899 eligible, --full-diff makes all three paths touched by the commit (ignoring the paths you gave from the command line) to be fed to the diff machinery, and pickaxe picks git-fetch.sh because that is the only one that changes "state". For the same reason, you would see git-fetch.sh out of this one:

    $ git log -p -1 -Sstate --full-diff b3d9899 -- pkt-line.c
Truly finally.
If you add --pickaxe-all to the last one:
    $ git log -p -1 -Sstate --pickaxe-all --full-diff b3d9899 -- pkt-line.c

pkt-line.c makes b3d9899 eligible, --full-diff feeds three changed paths to diff machinery, pickaxe notices that one of them (git-fetch.sh which is different from what you gave from the command line) changes "state", --pickaxe-all causes all three incoming paths to be output.

Jeff King· Dec 20, 2006, 08:41 UTC · re: Junio C Hamano · lore

[PATCH] revision: add --no-full-diff command line option

Signed-off-by: Jeff King <peff@peff.net>
---
On Wed, Dec 20, 2006 at 12:14:14AM -0800, Junio C Hamano wrote:
Show 5 quoted lines
> > I use --full-diff all the time, so this should save some typing. I can't
> > think of a time when I wouldn't want it on, but if there is, we probably
> > need a --no-full-diff.
> 
> Absolutely.
I took this to mean "absolutely we need --no-full-diff." :)

I note that --full-diff sets rev->diff = 1. The log.fulldiff config option does not, and nor does --no-full-diff unset it. However, I'm not sure it makes sense to set it. Doing "git-log --full-diff" outputs an extra line (separating the diff from the commit log) but since we haven't told it any type of diff to output, the diff is blank. And if we had told it a type, then that would have turned on rev->diff. So I don't see a point in setting it.

 revision.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
Show changes to revision.c +4 −0
diff --git a/revision.c b/revision.c
index 56819f8..ac4dbf2 100644
--- a/revision.c
+++ b/revision.c
@@ -955,6 +955,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
 				revs->full_diff = 1;
 				continue;
 			}
+			if (!strcmp(arg, "--no-full-diff")) {
+				revs->full_diff = 0;
+				continue;
+			}
 			if (!strcmp(arg, "--full-history")) {
 				revs->simplify_history = 0;
 				continue;
-- 
1.4.4.2.gee7ba-dirty
Junio C Hamano· Dec 20, 2006, 19:55 UTC · re: Jeff King · lore
Jeff King <peff@peff.net> writes:
Show 11 quoted lines
> Signed-off-by: Jeff King <peff@peff.net>
> ---
> On Wed, Dec 20, 2006 at 12:14:14AM -0800, Junio C Hamano wrote:
>
>> > I use --full-diff all the time, so this should save some typing. I can't
>> > think of a time when I wouldn't want it on, but if there is, we probably
>> > need a --no-full-diff.
>> 
>> Absolutely.
>
> I took this to mean "absolutely we need --no-full-diff." :)
Modulo s/\.$/, if we were to do log.fulldiff/, yes.
Show 7 quoted lines
> I note that --full-diff sets rev->diff = 1. The log.fulldiff config
> option does not, and nor does --no-full-diff unset it. However, I'm not
> sure it makes sense to set it. Doing "git-log --full-diff" outputs an
> extra line (separating the diff from the commit log) but since we
> haven't told it any type of diff to output, the diff is blank. And if we
> had told it a type, then that would have turned on rev->diff. So I don't
> see a point in setting it.
I need to think about this one.
Jeff King· Dec 20, 2006, 08:58 UTC · re: Junio C Hamano · lore

Re: [PATCH] add log.fulldiff config option

On Wed, Dec 20, 2006 at 12:14:14AM -0800, Junio C Hamano wrote:
> > Also, should this instead be diff.fulldiff?
> 
> Probably not.
Based on your explanation, I think that makes sense.
Show 5 quoted lines
> > Also also, I was going to submit a patch to document --full-diff,
> > but I had a few questions. Should it go in diff-options? That makes some
> > sense to me, but the parsing actually happens in setup_revisions.
> 
> Not at all.

Then where should it go? whatchanged and log have a great deal of overlap in terms of parsing, but they don't seem to share any documentation (or note the fact that git-whatchanged is basically just git-log -p).

> > Furthermore, it seems to do the same thing as --pickaxe-all. Should we
> > try to combine these?
> 
> No.

Thanks for the thorough explanation. I think this makes my config option description a little bit off, then, since it doesn't actually show all of the changed files for a commit in the case of pickaxe.

What has me confused, then, is that you said this:
Show 7 quoted lines
> I typically do:
> 
>         git log --full-diff -p -SCOLLISION
> 
> The --full-diff option helps because it shows the diff for other
> files (that do not have different number of substring COLLISION
> in the pre and postimage) in the same commit as well.

But that isn't the case, AFAIK (e.g., the command line you mention shows only changes to sha1_file.c in commit aac17941, but cache.h was also changed). Did you mean --pickaxe-all?

> Your understanding needs to be clarified on how paths are
> filtered, and how log family and diff interacts, and probably
> these need to be better documented.

To be honest, I'm not sure when one would really _want_ the flexibility this provides. It might be more intuitive to git-{log,whatchanged} users to have a single option (config and command line) to set --full-diff and --pickaxe-all together. At the very least, I think I now want a diff.pickaxeall config option.

Junio C Hamano· Dec 20, 2006, 10:01 UTC · re: Junio C Hamano · lore

Re: [PATCH] add log.fulldiff config option

Junio C Hamano <junkio@cox.net> writes:
> Your understanding needs to be clarified on how paths are
> filtered, and how log family and diff interacts, and probably
> these need to be better documented.

Having said that, I realized that I was making the same mistake that our existing documentation was criticized for.

Let me first digress to address the documentation criticism. The description on plumbing were (and still are) far more thorough than porcelain-ish, and the conjecture by the person who criticized them was because developers were keen documenting the real work (plumbing) soon after they finished coding than the frill (porcelain-ish).

I think the real reason for this is somewhat different. At least to me, git.git was about the plumbing, and I did not want to be in the Porcelain business at all [*1*]. Instead, I wanted to encourage healthy competition among Porcelains. What was shipped with git.git was meant to be "barely usable examples". But this vision has not materialized fully yet, fortunately because we did not end up splitting the userbase too early on. But this was unfortunate for two reasons. One of them is that different Porcelains would have brought completely different ways of thinking and workflows into the picture.

Because git.git was primarily about the plumbing, the main focus of the interface the plumbing offers was not about integration and uniformity but modularity. Designing them as independent building blocks as much as practical, and describing them fully, were part of completing the plumbing. And the "barely usable examples" started their lives as a set of trivial pipelines, whose meaning was quite obvious and straightforward when you understand the plumbing parts used in them. It also had UI warts. "barely usable examples" cheated their command line parsing, and the flags used by the plumbing showed through its thin veneer to the UI used by the end users.

But that was a long time ago. Now we are in the v1.5.0 process, whose theme is "usability and teachability".

Now, viewing in that light, what I described in the previous message may have been a precise description of how things happen to work currently, but it was not about the reason how and why they were designed to be (because there was little design at the UI level). We should instead (or at least "in addition") be talking more about how things ought to be.

I described why --full-diff and --pickaxe-all are different options, you can give 4 combinations of them, and how the combinations work differently and why. That does not justify that all of these four combinations make sense. In fact, I do not think they do.

When pickaxe is used and --full-diff is given to 'log', I think it does not make any sense not to use --pickaxe-all. So, I think at the level of log family commands, unifying these two flags make a lot of sense (although I earlier said "no").

Although --diff-filter does not have a corresponding option that makes it behave all-or-none (i.e. an equivalent to --pickaxe-all), it is conceivable that you might want to say:

    $ git log --diff-filter=A --full-diff --diff-filter-all

to view commits that add new files with full diffs (not just added paths). If we were to add that, I think it makes sense to internally have a flag separate from pickaxe-all to express it but when 'log' uses --full-diff, it does not make any sense not to enable it. In other words,

    $ git log -M --diff-filter=R -Sstring --full-diff

should internally enable pickaxe-all and diff-filter-all and show all of diff that has renames in the paths that change "string" [*2*].

[Footnote]

*1* I once wanted to do a Porcelain of my own, after finding it distasteful that Cogito tried to hide the index back when it did not even use the index properly for merges. But things have been improved quite a lot in Cogito land and I do not have anything against it anymore. And as you all know, I like StGIT very much.

*2* This is actually in line with what we did in 582af688. As a member of 'log' family, 'git log' were originally meant to show commit messages for all commits that revision traversal gave it, regardless of the diff output (and without the diffcore transformation, when revision traversal said a commit is interesting, the commit always has some diff or a merge). When used in conjunction with --pickaxe and --diff-filter, however, this layering made the command much less useful. We fixed the problem by violating the layering and made the log command aware of the underlying diff machinery's output filter. I think the same would apply to the issue we are currently discussing.

← back to recent threads