412

I am trying to exclude a file (db/irrelevant.php) from a Git diff. I have tried putting a file in the db subdirectory called .gitattributes with the line irrelevant.php -diff and I have also tried creating a file called .git/info/attributes containing db/irrelevant.php.

In all cases, the db/irrelevant.php file is included in the diff as a Git binary patch. What I want is for the changes to that file to be ignore by the diff command. What am I doing wrong?

syntagma
  • 23,346
  • 16
  • 78
  • 134
Michael
  • 4,597
  • 2
  • 17
  • 16

15 Answers15

546

Omg, drivers and awk to exclude a lousy file? Since Git 1.9 something you can:

git diff -- . ':(exclude)db/irrelevant.php' ':(exclude)db/irrelevant2.php'

(On Windows, replace the single quotes ' by double quotes ".)

Ah, elegance! See the quoted answer and for details this answer by @torek.

Michael
  • 8,362
  • 6
  • 61
  • 88
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
  • 5
    NOTE: If you want to exclude a specific file name you have to prefix with asterisk, different from the `.gitignore` file syntax. E.g. `:!*shrinkwrap.yaml` instead of `:!shrinkwrap.yaml`. – vaughan Jan 19 '18 at 10:38
  • 20
    Exclude more files, E.g. I have *.min.css and *.min.js files to avoid from the git diff. So, I use the command `git diff -- . ':(exclude)*.min.js' ':(exclude)*.min.css'` – maheshwaghmare Apr 19 '18 at 10:28
  • 8
    **windows syntax** : `git diff -- . ":(exclude)db/irrelevant.php"` (double quotes instead of single quotes) – cnlevy Apr 24 '18 at 15:22
  • 9
    Thank you! Such an esoteric syntax.. I have to look it up every time. – Daniel Waltrip Feb 12 '19 at 22:57
  • 2
    @cnlevy or no quotes! `git diff -- . :(exclude)db/irrelevant.php` – Matthias Apr 28 '19 at 22:11
  • 14
    `git diff -- . ':(exclude)package-lock.json'` -- for a (probably) very common case here's command line to copy-paste. – Septagram May 23 '19 at 18:24
  • 3
    Would it be possible to add this co .gitconfig file so `git diff` always runs with this by default? – dominikduda Aug 20 '19 at 09:06
  • 1
    For those wondering why it doesn't work for them, the "." is required (or some pathspec). Just plain "git diff ':!yarn.lock" will still diff yarn.lock. You need "git diff . ':!yarn.lock'". Elegance indeed... :-/ – GaryO Mar 22 '20 at 20:56
  • 1
    @dominikduda [no](https://stackoverflow.com/questions/3538774/is-it-possible-to-override-git-command-by-git-alias). but you can `git config alias.diff2 "diff -- :/ ':(exclude,top)src/ignore-me.txt'"` and use `git diff2` – milahu Dec 03 '20 at 11:51
  • 1
    Please note that the '.' is important. The '':(exclude)' syntax works only if there is an incluse specification 'the '.' If you forget this, you have a error that looks like: `fatal: There is nothing to exclude from by :(exclude) patterns.` – Johann Bzh May 27 '21 at 08:39
  • `"` is only needed for cmd, not Powershell. – Oskar Apr 27 '22 at 12:48
128

This method is shorter than the accepted answers.

git diff 987200fbfb 878cee40ba -- ':!*.cs'

For more information about the different inclusion/exclusion possibilities read this other post

legends2k
  • 31,634
  • 25
  • 118
  • 222
chtenb
  • 14,924
  • 14
  • 78
  • 116
77

You could set up a custom diff driver with a no op command and assign it to those files that should be ignored.

Create a repository specific diff driver with this command

git config diff.nodiff.command /bin/true

or for all your repos with --global.

(If /bin/true doesn't exist in MacOS, alternatives would be using /usr/bin/true or echo).

Then, assign the new diff driver to those files you want ignored in your .git/info/attributes file.

irrelevant.php    diff=nodiff

If this state is supposed to be shared with other developers you could use .gitattributes instead of .git/info/attributes and share the git config command with your peers (through a documentation file or something).

KurzedMetal
  • 12,540
  • 6
  • 39
  • 65
  • 2
    This is exactly what I was looking for - as described in http://kerneltrap.org/mailarchive/git/2008/10/17/3711254 I edited ~/.gitconfig adding: `[diff "nodiff"]` ` command = /bin/true` and I then created a file called .git/info/attributes into which I added: `irrelevant.php diff=nodiff` – Michael Jun 13 '12 at 09:38
  • 15
    This answer worked much better for me: http://stackoverflow.com/questions/1016798/excluding-files-from-git-diff – Neil Forrester Sep 08 '13 at 16:11
  • 3
    Interestingly this approach does not work with `git diff --stat`. In that case, one could use `git diff ... | diffstat` as a workaround. – ddkilzer Nov 06 '13 at 19:42
  • @Michael that link appears to be borked, is there another? – DickieBoy Jul 16 '15 at 12:19
  • 4
    just an addition: if you want to force git diff to display it anyway, use `--no-ext-diff` – Florian Klein Aug 12 '15 at 16:06
  • It works! In a Windows command prompt, I used `true` in place of `/bin/true`. (`echo` had a weird effect on the diff, getting hung up momentarily when I hit `q` to exit the diff.) – Ryan Lundy May 19 '16 at 12:36
  • `git diff --exit-code` will exit with `1` with this used, as if there were differences. – gsnedders Jan 04 '17 at 14:36
76

Simplest answer

git diff ':!db/irrelevant.php'

It's just ':!<path>' after your diff command. The diff command can be as complicated as you like, and you can use wildcards like *.min.js or add multiple excludes (space separate the quoted blocks) if you want.

dlsso
  • 7,209
  • 1
  • 21
  • 31
  • 3
    Thanks! works great for `git log -p` as well. As in: `git log -p ':!package-lock.json'` – David Jan 23 '22 at 00:47
  • The most-effective answer for me. Excludes only the specific file in question (and nice tip on 'git log -p', too @David). Quite effictive for what our team calls "git mid-edit saves" when you want to "backup save" a large set of untested (and therefore uncertified by the developer) git edits without making a more-official "commit"; like this (in a `.bash_profile` or some such): `gd_file="./2-git-diff-mid-edit-save.diff.txt"; alias git_mid_edit_save="git diff ':!$gd_file' > $gd_file; git add $gd_file; git commit -m 'mid-edit save'; git push -u"` – Johnny Utahh Apr 17 '22 at 21:49
  • Latest version of my immediately-above code here: https://gist.githubusercontent.com/johnnyutahh/e8cfb515fb65635dca520117477456b8/raw – Johnny Utahh Apr 17 '22 at 21:55
40

You can also use filterdiff program of the patchutils program collection to exclude some parts of a diff. For example:

git diff | filterdiff -p 1 -x db/irrelevant.php
Szilárd Pfeiffer
  • 1,636
  • 1
  • 12
  • 6
  • 4
    Note that `-p`, from the manpage(1), is "-p n, --strip-match=n When matching, ignore the first n components of the pathname." It took me a while to catch that `-p 1` was removing the `db` part from the OP's path. If you just want to specify a filename and ignore all path/dir possibilities, you can use `-p 99`. – Tyler Collier Apr 29 '14 at 00:34
37

Really good answer from KurzedMetal for what I needed to do, which was ability to see that the file has changed, but not to generate the diff, which could have been huge, in my case.

But a colleague of mine suggested approach that was even simpler and worked for me:

adding .gitattributes file in the directory where the file to be ignored by git diff resides with the following content:

file-not-to-diff.bin -diff

That still lets git status "see" if the file changed. git diff will also "see" that the file changed, but it will not generate the diff.

That .bin extension for the file in the example was deliberate. I do realize that this is the default behavior of git for binary files, and it does not require special handling with .gitattributes. But in my case, these files were recognized as text files by git and "file" utility, and this did the trick.

user3589608
  • 469
  • 4
  • 5
  • 2
    Yes! This is neat and tidy, it doesn't hide that anything changed, but won't show you ugly-ass `*.min.js` files and the like. This is excellent, the best answer IMHO. – odinho - Velmont Jul 02 '20 at 12:31
  • 1
    Awesome answer. clear and simple.. Kudos – Siddaram H Oct 06 '21 at 02:46
  • 1
    Just what I was looking for! Git Extensions on Windows by default automatically shows diffs for .pdf files which is often quite time consuming. This allowed me to disable the diff specifically for the .pdf, but still easily commit the most recent version. – Ben JW Oct 13 '21 at 13:25
  • 4
    This should be the accepted answer. – Peter Feb 14 '22 at 16:07
  • 2
    It really should: no one wants to have to type a bunch of arguments every time they `git diff`. This solutions let's you fix it once and forget about the issue forever. – machineghost Apr 25 '22 at 16:48
  • 1
    If you have a per-developer config file (i.e. `.sbtopts` in my case) and you want to use `--assume-unchanged` but don't want it showing up in diffs for local changes - this solution is perfect. – noahlz Aug 01 '22 at 23:10
16

This one-line solution requires no other utils/downloads:

git diff `git status -s |grep -v ^\ D |grep -v file/to/exclude.txt |cut -b4-`

Where file/to/exclude.txt is the name of the file you would like to exclude, of course.

Edit: credit ksenzee for fixing deleted files breaking the diff.

Community
  • 1
  • 1
Ben Roux
  • 7,308
  • 1
  • 18
  • 21
11

Relative to the git root directory

git diff accepts an optional exclude

git diff -- ":(exclude)thingToExclude"

You might want to add some wild cards

git diff -- ":(exclude)*/thingToExclude/*"

Target specific file types

git diff -- ":(exclude)*/$1/*.png"

Or drop a little script for your dotfiles

Such as .bash_profile or .zshrc

gde() {
    # git diff exclude files or folders 
    # usage: 
    # gde fileOrFolderNameToExclude
    git diff -- ":(exclude)*/$1/*"
}
jasonleonhard
  • 12,047
  • 89
  • 66
  • this just does not work for me, I get no diff at all, with both syntaxes, using (exclude) or !. I have git 2.21.0 – Olivvv Oct 14 '19 at 12:52
  • You can git diff either unstaged or staged files. If you have git added them they become staged. If they are staged you can do ```git diff --staged``` Hope this helps you. – jasonleonhard Oct 14 '19 at 14:38
  • Syntactically, what is the colon doing? – Jonah Feb 18 '20 at 17:46
8

Building on existing answers, if you want to exclude a file pattern no matter where it is in the directory, use the corresponding git pathspec value of **:

git diff -- ':!**/yarn.lock'
Carl G
  • 17,394
  • 14
  • 91
  • 115
3

I do the following:

git add *pattern_to_exclude*
git diff
git reset HEAD .

I know it's not an elegant solution and it sometimes canot be used (eg. if you already have stuff staged) , but it does the trick without having to type a complicated command

BlueMagma
  • 2,392
  • 1
  • 22
  • 46
2

It's very simple, you can exclude what you want using standard unix commands, those commands are available under git bash even under windows environment. Below example shows how to exclude diff for pom.xml files, first check diff to master only for filenames, then using 'grep -v' exclude files which you don't want and then run again diff to master with prepapred list:

git diff master `git diff --name-only master | grep -v pom.xml`
1

similar to Ben Roux's solution, but sharing anyway:

git status --porcelain | grep -v $PATTERN_TO_EXCLUDE | awk '{print $2}' | xargs git diff

or, if the changes have already be committed locally:

git diff --name-only origin/master | grep -v $PATTERN_TO_EXCLUDE | xargs git diff origin/master

Examples:

git status --porcelain | grep -v docs | awk '{print $2}' | xargs git diff origin/master

git diff --name-only origin/master | grep -v docs | xargs git diff origin/master
Community
  • 1
  • 1
1

My workaround

git add .
git reset <list of files to ignore>
git diff --cached
o01
  • 5,191
  • 10
  • 44
  • 85
0

If you want to do this only to visually inspect the diff, a visual diff tool (like Meld) will let you do it with a short command that's easy to remember.

First, set up a diff tool if you haven't already.

$ git config --global diff.tool = meld

Then, you can run a directory diff.

$ git difftool --dir-diff

You'll be able to browse diffs (by file) in Meld (or your tool of choice). Simply don't open the file you want to ignore.

mkasberg
  • 16,022
  • 3
  • 42
  • 46
0
git diff remote/master..master --name-only -- ':!README.rst'

Gave me (git version 2.11.0)

fatal: There is nothing to exclude from by :(exclude) patterns.
Perhaps you forgot to add either ':/' or '.' ?
git diff remote/master..master --name-only -- './*' ':!README.rst'

Worked nicely, source: https://stackoverflow.com/a/30084612/5155484

William Desportes
  • 1,412
  • 1
  • 22
  • 31