threads / discuss / 15938

Excluding files from git-diff

Subject: Excluding files from git-diff

## tl;dr

12 messages between Oct 17, 2008 and Oct 18, 2008.

replies: 11people: 8as markdown or json

Erik Hahn· Oct 17, 2008, 14:53 UTC · lore

I'm currently working on a script whose developer does not use git. Hence, when I mail him the patch, I don't want to include the .gitignore file. Is it possible to exclude a file from git-diff (except not adding it to git, of course?)

	-Erik
-- 
hackerkey://v4sw5hw2ln3pr5ck0ma2u7LwXm4l7Gi2e2t4b7Ken4/7a16s0r1p-5.62/-6.56g5OR
Raphael Zimmerer· Oct 17, 2008, 15:08 UTC · re: Erik Hahn · lore

Re: Excluding files from git-diff

On Fri, Oct 17, 2008 at 04:53:13PM +0200, Erik Hahn wrote:
> I'm currently working on a script whose developer does not use
> git. Hence, when I mail him the patch, I don't want to include the
> .gitignore file. Is it possible to exclude a file from git-diff (except
> not adding it to git, of course?)

Just add the content of .gitignore to .git/info/exclude, and remove .gitignore from the repository.

Raphael
Johannes Schindelin· Oct 17, 2008, 15:08 UTC · re: Erik Hahn · lore

Re: Excluding files from git-diff

Hi,
On Fri, 17 Oct 2008, Erik Hahn wrote:
> I'm currently working on a script whose developer does not use git. 
> Hence, when I mail him the patch, I don't want to include the .gitignore 
> file. Is it possible to exclude a file from git-diff (except not adding 
> it to git, of course?)
You can specify everything else:
	git diff -- *

Hth, Dscho

Michael J Gruber· Oct 17, 2008, 15:18 UTC · re: Erik Hahn · lore

Re: Excluding files from git-diff

Erik Hahn venit, vidit, dixit 17.10.2008 16:53:
> I'm currently working on a script whose developer does not use
> git. Hence, when I mail him the patch, I don't want to include the
> .gitignore file. Is it possible to exclude a file from git-diff (except
> not adding it to git, of course?)

Am I right in assuming that by "script" you mean a manuscript consisting of several files, rather than a single script (programme in scripting language)? In any case:

git diff commit1 commit2 file

gives you the diff for "file" between those commits, so if you're really interested in one file that's the way to go; you can also specify more than one file here.

On the other hand, your .gitignore probably doesn't change that often, so that it shouldn't show up in the diff after that anyways. Or put it in .git/info/excludes.

Cheers, Michael

Christian Jaeger· Oct 17, 2008, 16:30 UTC · re: Michael J Gruber · lore

Re: Excluding files from git-diff

Michael J Gruber wrote:
> your .gitignore probably doesn't change that often,
> so that it shouldn't show up in the diff after that anyways. Or put it
> in .git/info/excludes.

For me, adding entries to that file does not make "git diff" or "gitk" or even "git ls-files" ignore files matching the entries. Only "git ls-files --others --exclude-from=.git/info/exclude" will exclude them. And "git diff " and gitk don't seem to know the --exclude-from option.

Is there a way to really invert the patterns given to "git diff" or alike? I.e. instead of saying "git diff -- * .somedotfile .someothernongitignoredotfile" one could just say something like "git diff --invert-matches -- .gitignore"? And even better, could one configure some such so that it has effect on all tools by default?

(That would help working around the clutter problem from the "Separating generated files?" thread; i.e. in some cases this could be good enough to not require splitting a project into multiple repositories. (Although I'm all the same currently working on a "intergit-find-matching-commit-in" script, since there may be more good reasons than only the clutter to split projects.))

Christian.
Eric Raible· Oct 17, 2008, 17:33 UTC · re: Christian Jaeger · lore

Re: Excluding files from git-diff

Christian Jaeger <christian <at> pflanze.mine.nu> writes:
Show 6 quoted lines
> 
> Michael J Gruber wrote:
> > Or put it
> > in .git/info/excludes.
> 
> Only "git ls-files --others --exclude-from=.git/info/exclude" will exclude
Could it be a simple as "excludes" vs "exclude"?
- Eric
Christian Jaeger· Oct 18, 2008, 03:50 UTC · re: Eric Raible · lore

Re: Excluding files from git-diff

Eric Raible wrote:
Show 13 quoted lines
> Christian Jaeger <christian <at> pflanze.mine.nu> writes:
>
>   
>> Michael J Gruber wrote:
>>     
>>> Or put it
>>> in .git/info/excludes.
>>>       
>> Only "git ls-files --others --exclude-from=.git/info/exclude" will exclude
>>     
>
> Could it be a simple as "excludes" vs "exclude"?
>   
Nope.

ln -s exclude .git/info/excludes git ls-files # still shows files matching the excludes git ls-files --exclude-from=.git/info/exclude # does not show git ls-files --exclude-from=.git/info/excludes # does not show

Christian.
Jeff King· Oct 18, 2008, 15:59 UTC · re: Christian Jaeger · lore

Re: Excluding files from git-diff

On Fri, Oct 17, 2008 at 06:30:31PM +0200, Christian Jaeger wrote:
> For me, adding entries to that file does not make "git diff" or "gitk" or 
> even "git ls-files" ignore files matching the entries. Only "git ls-files 
> --others --exclude-from=.git/info/exclude" will exclude them. And "git 
> diff " and gitk don't seem to know the --exclude-from option.
What you are seeing is:
  - ls-files is plumbing, and does not do any exclusion by default. So
    you need to use the --exclude-from option, or more easily,
    --exclude-standard (which pulls in .git/info/excludes, .gitignore,
    and user-level excludes).
  - porcelain _does_ do exclusion. However, exclusion does not mean "if
    this file is tracked by git, don't include it in the diff." It
    merely means "if this file is untracked, pretend like it is not
    there." So a diff displayed by "git diff" isn't affected by
    exclusions anyway.
Show 5 quoted lines
> Is there a way to really invert the patterns given to "git diff" or  
> alike? I.e. instead of saying "git diff -- * .somedotfile  
> .someothernongitignoredotfile" one could just say something like "git  
> diff --invert-matches -- .gitignore"? And even better, could one  
> configure some such so that it has effect on all tools by default?

No, I don't think there is a way to do that currently. I would probably generate the file list with a shell snippet:

  git diff -- `git ls-files | grep -v .gitignore`

but obviously that is a lot more typing if this is something you are doing frequently.

-Peff
Christian Jaeger· Oct 18, 2008, 16:08 UTC · re: Jeff King · lore

Re: Excluding files from git-diff

Jeff King wrote:
Show 7 quoted lines
> No, I don't think there is a way to do that currently. I would probably
> generate the file list with a shell snippet:
>
>   git diff -- `git ls-files | grep -v .gitignore`
>
> but obviously that is a lot more typing if this is something you are
> doing frequently.

The problem with this is that it won't show files that aren't there anymore but have been previously; in general, for that to work (also with git log, for example), the list of files would need to include all paths which have ever existed and which are not to be excluded. Even then, I'm not sure whether there are corner case where it would not work (when files are being renamed, for example?).

If I/we (after finishing my intergit-find-matching-commit-in experiment) finally decide that tracking generated files in the same repository is the right thing to do, then I guess the only way to ignore those cleanly would be to add an inverse match feature to the Git core.

Christian.
Jeff King· Oct 18, 2008, 16:14 UTC · re: Christian Jaeger · lore

Re: Excluding files from git-diff

On Sat, Oct 18, 2008 at 06:08:55PM +0200, Christian Jaeger wrote:
> The problem with this is that it won't show files that aren't there  
> anymore but have been previously; in general, for that to work (also with 

Yes, you're right. You really do want to be telling git not "here is the list of files I care about" but "I really care about anything _except_ this set".

And I don't think that is currently possible, so a patch would be necessary (and I think is justified, since there is no other way to do it).

The most flexible thing would be the ability to say "I want these paths (or all paths), and exclude these paths" (sort of like we already do for commits). But defining a good command-line syntax for that would probably be painful, and I really think the only sane use case is "I want all paths except for these". In which case your "--invert-match" seems like a good route.

-Peff
Jeff King· Oct 18, 2008, 16:58 UTC · re: Jeff King · lore

Re: Excluding files from git-diff

On Sat, Oct 18, 2008 at 12:14:24PM -0400, Jeff King wrote:
Show 6 quoted lines
> The most flexible thing would be the ability to say "I want these paths
> (or all paths), and exclude these paths" (sort of like we already do for
> commits). But defining a good command-line syntax for that would
> probably be painful, and I really think the only sane use case is "I
> want all paths except for these". In which case your "--invert-match"
> seems like a good route.

I looked at this a little, so here's as far as I got, in case it helps you in writing a patch.

There are actually two ways the limiter is used:
 1. diff will show only a subset of the paths, as contained in a
    diff_options.paths variable
 2. the revision walker will prune based based on changes in particular
    paths (e.g., "git log --invert-path -- .gitignore" should show only
    commits that touch something besides .gitignore)

The code to handle '1' might look something like the patch below, but this doesn't deal at all with revision pruning.

---
diff --git a/diff.c b/diff.c
index 1c6be89..a72f593 100644
--- a/diff.c
+++ b/diff.c
@@ -2646,6 +2646,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
 		DIFF_OPT_CLR(options, ALLOW_EXTERNAL);
 	else if (!strcmp(arg, "--ignore-submodules"))
 		DIFF_OPT_SET(options, IGNORE_SUBMODULES);
+	else if (!strcmp(arg, "--invert-path"))
+		DIFF_OPT_SET(options, INVERT_PATH);
 
 	/* misc options */
 	else if (!strcmp(arg, "-z"))
diff --git a/diff.h b/diff.h
index a49d865..43f3bff 100644
--- a/diff.h
+++ b/diff.h
@@ -65,6 +65,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
 #define DIFF_OPT_IGNORE_SUBMODULES   (1 << 18)
 #define DIFF_OPT_DIRSTAT_CUMULATIVE  (1 << 19)
 #define DIFF_OPT_DIRSTAT_BY_FILE     (1 << 20)
+#define DIFF_OPT_INVERT_PATH         (1 << 21)
 #define DIFF_OPT_TST(opts, flag)    ((opts)->flags & DIFF_OPT_##flag)
 #define DIFF_OPT_SET(opts, flag)    ((opts)->flags |= DIFF_OPT_##flag)
 #define DIFF_OPT_CLR(opts, flag)    ((opts)->flags &= ~DIFF_OPT_##flag)
diff --git a/tree-diff.c b/tree-diff.c
index 9f67af6..ef78d91 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -91,7 +91,7 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
  *  - zero for no
  *  - negative for "no, and no subsequent entries will be either"
  */
-static int tree_entry_interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt)
+static int tree_entry_interesting_internal(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt)
 {
 	const char *path;
 	const unsigned char *sha1;
@@ -190,6 +190,17 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int
 	return never_interesting; /* No matches */
 }
 
+static int tree_entry_interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt)
+{
+	int r = tree_entry_interesting_internal(desc, base, baselen, opt);
+	if (!DIFF_OPT_TST(opt, INVERT_PATH))
+		return r;
+	return r  < 0 ?     2 :
+	       r == 0 ?     1 :
+	       r == 1 ?     0 :
+	       /* r > 1 */ -1;
+}
+
 /* A whole sub-tree went away or appeared */
 static void show_tree(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base, int baselen)
 {
Anders Melchiorsen· Oct 17, 2008, 23:38 UTC · re: Erik Hahn · lore

Re: Excluding files from git-diff

Erik Hahn wrote:
Show 5 quoted lines
> I'm currently working on a script whose developer does not use
> git. Hence, when I mail him the patch, I don't want to include the
> .gitignore file. Is it possible to exclude a file from git-diff (except
> not adding it to git, of course?)
>   

I don't think that this is what you are asking about, but it's a neat trick anyway :-).

To permanently exclude files from git diff, set up a custom diff driver in ~/.gitconfig:

[diff "nodiff"]
    command = /bin/true

and then mention the files that should use this driver in .git/info/attributes:

.gitignore diff=nodiff

← back to recent threads