Git command to show which specific files are ignored by .gitignore

Viewed 431917

I am getting my feet wet with Git and have the following issue:

My project source tree:

/
|
+--src/
+----refs/
+----...
|
+--vendor/
+----...

I have code (currently MEF) in my vendor branch that I will compile there and then move the references into /src/refs which is where the project picks them up from.

My issue is that I have my .gitignore set to ignore *.dll and *.pdb. I can do a git add -f bar.dll to force the addition of the ignored file which is ok, the problem is I can not figure out to list what files exist that are ignored.

I want to list the ignored files to make sure that I don't forget to add them.

I have read the man page on git ls-files and can not make it work. It seems to me that git ls-files --exclude-standard -i should do what I want. What am I missing?

13 Answers

Notes:


Also interesting (mentioned in qwertymk's answer), you can also use the git check-ignore -v command, at least on Unix (doesn't work in a CMD Windows session)

git check-ignore *
git check-ignore -v *

The second one displays the actual rule of the .gitignore which makes a file to be ignored in your git repo.
On Unix, using "What expands to all files in current directory recursively?" and a bash4+:

git check-ignore **/*

(or a find -exec command)

Note: https://stackoverflow.com/users/351947/Rafi B. suggests in the comments to avoid the (risky) globstar:

git check-ignore -v $(find . -type f -print)

Make sure to exclude the files from the .git/ subfolder though.

CervEd suggests in the comments, to avoid .git/:

find . -not -path './.git/*' | git check-ignore --stdin

Original answer 42009)

git ls-files -i

should work, except its source code indicates:

if (show_ignored && !exc_given) {
                fprintf(stderr, "%s: --ignored needs some exclude pattern\n",
                        argv[0]);

exc_given ?

It turns out it need one more parameter after the -i to actually list anything:

Try:

git ls-files -i --exclude-from=[Path_To_Your_Global].gitignore

(but that would only list your cached (non-ignored) object, with a filter, so that is not quite what you want)


Example:

$ cat .git/ignore
# ignore objects and archives, anywhere in the tree.
*.[oa]
$ cat Documentation/.gitignore
# ignore generated html files,
*.html
# except foo.html which is maintained by hand
!foo.html
$ git ls-files --ignored \
    --exclude='Documentation/*.[0-9]' \
    --exclude-from=.git/ignore \
    --exclude-per-directory=.gitignore

Actually, in my 'gitignore' file (called 'exclude'), I find a command line that could help you:

F:\prog\git\test\.git\info>type exclude
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

So....

git ls-files --ignored --exclude-from=.git/info/exclude
git ls-files -i --exclude-from=.git/info/exclude

git ls-files --others --ignored --exclude-standard
git ls-files -o -i --exclude-standard

should do the trick.

(Thanks to honzajde pointing out in the comments that git ls-files -o -i --exclude-from... does not include cached files: only git ls-files -i --exclude-from... (without -o) does.)

As mentioned in the ls-files man page, --others is the important part, in order to show you non-cached, non-committed, normally-ignored files.

--exclude_standard is not just a shortcut, but a way to include all standard "ignored patterns" settings.

exclude-standard
Add the standard git exclusions: .git/info/exclude, .gitignore in each directory, and the user's global exclusion file.

Another option that's pretty clean (No pun intended.):

git clean -ndX

Explanation:

$ git help clean

git-clean - Remove untracked files from the working tree
-n, --dry-run - Don't actually remove anything, just show what would be done.
-d - Remove untracked directories in addition to untracked files.
-X - Remove only files ignored by Git.

Note: This solution will not show ignored files that have already been removed.

If you just need a valid list of files ignored (no matter how they got ignored), and without any extra notice and logs.

Once created, anywhere (in Git-bash) run:

git ignore-list

Create it by executing:

git config --global alias.ignore-list "! cd -- \"\${GIT_PREFIX:-.}\" && git ls-files -v \${1:-.} | sed -n -e \"s,^[a-z] \(.*\)$,\${GIT_PREFIX:-./}\1,p\" && git status --ignored --porcelain \${1:-.} 2>/dev/null | sed -n -e \"s/^\(\\!\\! \)\(.*\)$/\2/p\" #"

Example usage, Assuming it's the initial commit and you want to push everything, try:

git ignore-list | xargs git add -f

Notes:

  1. It's tested and works on both macOS and Windows platforms!
  2. Once you cd into a directory, lists only files ignored from that dir (or its sub-dirs).
  3. And lastly, always logs paths relative to root-dir (which contains .git dir, no matter what dir you cd into).

Another useful thing is Human-readability, like if an entire directory is ignored, something like build or node_modules, this will log dir-name only.
While git ls-files --others -i --exclude-standard command logs each and every file (good for xargs).

I would just do

git status --porcelain --ignored

and to only list the ignored files

git status --porcelain --ignored | grep '^[!][!] '

(extending the other answers)

Note, git check-ignore uses the committed .gitignore and not the one in your working tree! To play with it without polluting your git history, you might freely try to edit it, and then commit with a git commit --amend.

This problem happens mainly if you need a workaround of the problem, that git doesn't follow directories. Enter in the .gitignore:

dirtokeep/**
!dirtokeep/.keep

.keep should be a zero-length file in dirtokeep.

The result will be that everything in dirtokeep will be ignored, except dirtokeep/.keep, which will result that also the dirtokeep directory will be constructed on clone/checkout.

You can use fd.

The command to run is:

comm -23 <(fd -HI | sort) <(fd -H | sort) 

Please note that in case there is no .git directory and only a .gitignore file (ex. bare repo), you have to specifically tell where the .gitignore file is.

comm -23 <(fd -HI | sort) <(fd -H --ignore-file .gitignore | sort)

To be more specific, use --no-ignore-vcs instead of -I

For more details please check here.

If you want to remove those files by manually deleting them and have your project totally clear of files outside GIT you can run:

rm -rf $(git status --ignored)

WARNING: this will remove force ANY FILE AND DIRECTORY returned by git status --ignored. Use at your own discretion and only if you know what you're doing.

Related