63

I am tracking a project with git. There are some Xcode project files in the working copy that I want to keep tracking, but do not want to see in diffs, because there are always dozens of changed lines that I am never interested in. Is there a simple way to have git-diff skip these files? I’ve tried to set up a custom “silent” diff tool:

$ cat .gitattributes 
Project.xcodeproj/* diff=nodiff

$ cat ~/.gitconfig 
[diff "nodiff"]
    command = /bin/true

But:

$ git diff
external diff died, stopping at Project.xcodeproj/zoul.mode1v3.

What am I doing wrong?

zoul
  • 102,279
  • 44
  • 260
  • 354

4 Answers4

99

The problem is that /bin/true will return immediately without reading its input. git diff therefore thinks, quite reasonably, that it has died prematurely.

What you really want to do is to unset the diff attribute, not set it to a bogus command. Try this in your .gitattributes:

Project.xcodeproj/* -diff
Ken Williams
  • 22,756
  • 10
  • 85
  • 147
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 5
    Excluding the whole directory didn't work for me, because many of the files are in deeper subdirs. Instead *.xcuserstate -diff was helpful to ignore the often changing file. – Bemmu Dec 10 '11 at 04:13
  • @Bemmu: To be fair, I was only using the same pattern as in the question. There wasn't any suggestion that the pattern wasn't working in the original askers situation. – CB Bailey Dec 10 '11 at 09:15
  • 1
    Sure, just wanted to include this since it might help whoever is reading this to solve their situation. – Bemmu Dec 12 '11 at 10:40
  • 1
    A lot of similar questions on SO, couldn't find an answer as simple and effective as this! – user1445967 Aug 18 '14 at 18:35
  • 3
    I'm using Git 1.9.4 and adding `-diff` now makes diff process the files I want to exclude as binary files, instead of ignoring them... – slaadvak Sep 30 '14 at 20:25
  • 2
    If you want to exclude subdirectories as well, make it `Project.xcodeproj/**/* -diff` instead. – tomekwi May 27 '15 at 07:36
  • 1
    Also does not prevent external diff from processing it (may partly be because it only treats it as binary now instead of ignoring) – Steven Lu Dec 23 '15 at 02:20
  • @StevenLu You can fix this by patching your git-difftool--helper, see http://stackoverflow.com/a/7674147/2448947 – mstrange Dec 30 '15 at 20:09
  • Note that `.gitattributes` goes in your project directory with `.gitignore`, NOT in your home directory with `.gitconfig` – Zach Olivare Oct 12 '18 at 13:09
  • This recipe does not help for `git difftool`, while the recipe with `\bin\true` does help. – John Smith Feb 08 '23 at 13:57
7

You may use an alias in your .git/config

[alias]
        mydiff = !git diff | filterdiff -x "*/Project.xcodeproj/*"

You need filterdiff (from patchutils) for this trick.

sudo apt-get install patchutils

Still the diff isn't perfect, it leaves some garbage :

yannick@yannick-desktop:~/git-filter-test$ git mydiff
diff --git a/Project.xcodeproj/dummy.txt b/Project.xcodeproj/dummy.txt
index 3e1f9e6..89dfed9 100644
diff --git a/dummy2.txt b/dummy2.txt
index 91966ce..d9588a9 100644
--- a/titi.txt
+++ b/titi.txt
@@ -1,3 +1,3 @@
 aaaaaaaaaa
-bbbbbbbbb
 cccccc
+ddd
yanjost
  • 5,223
  • 2
  • 25
  • 28
  • This is very nice, thank you. The garbage is just fine, at least I know those files changed. But I lose the coloring, is there a way to get it back? I tried git diff --color to force it, but then filterdiff gets confused by the color escapes and stops filtering. – zoul Jun 19 '09 at 09:13
  • Oh yes, | colordiff | less -r. – zoul Jun 19 '09 at 09:20
  • Thanks for answers to this question -- filterdiff is nearly meeting my needs -- however, the "garbage" remaining is causing me trouble -- is there a way to say "completely remove all reference to a file" using filterdiff? – Michael Jun 12 '12 at 16:10
7

Another solution that produces clean output without any external tools (add to .git/config):

[alias]
    mydiff = !git diff -- $(git diff --name-only | grep -Ev "Project.xcodeproj/")

Then run it with:

git mydiff

Note that git diff --name-only is better than git ls-files because it will pass a shorter list of files to git diff, since only files that are modified will be included. I've run into trouble with exceeding the maximum number of arguments in large projects when using git ls-files.

Connor McKay
  • 580
  • 7
  • 13
  • I ran into issues with complex paths with this. I suspect it would better if you used the -z switch: "do not munge pathnames and use NULs as output field terminators". – Ben Creasy Sep 18 '15 at 06:24
1

Just incase someone else has the same pain we had. We wanted to exclude a file that had already been committed.

This post was way more useful: working with .git/info/exclude too late

Specifically what you need to ignore a file is actually use the command git remove See git rm (http://www.kernel.org/pub/software/scm/git/docs/git-rm.html)

you test it by going

git rm --dry-run *.log
(if you say wanted to exclude all the log files)

this will output what would be excluded if you ran it.

then

you run it by going

git rm *.log
(or whatever filename path / expression you want to)

Community
  • 1
  • 1
Evolve
  • 8,939
  • 12
  • 51
  • 63