721

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?

Matthias Braun
  • 24,493
  • 16
  • 114
  • 144
Andrew Burns
  • 12,329
  • 9
  • 36
  • 40
  • 12
    These days, you wouldn't use git-ls-files but rather 'git ls-files' – wojo Jun 10 '09 at 20:40
  • 7
    I plead with you to check [riyad's answer](http://stackoverflow.com/a/1446609/10608) as correct since that is the only one that admits there's no _guaranteed_ way to do this using only git commands (including the `git clean` trick) as demonstrated [here](https://github.com/Thr4wn/myths_about_git_show_all_ignored_files). Also, I recommend against the "exclude-from" example in your summary since that factually doesn't pay attention to any .gitignore files. I ask this especially because this page is the top Google response. – Alexander Bird Oct 26 '12 at 01:19
  • Quick point on "Summary of what works": the "Git ls-files" man page explains that the "-i" means include excluded files for the ls output. I had the same misunderstanding, until I read 'it slowly'. ;-) – will May 01 '14 at 08:07
  • 2
    Answers should go in an answer post and not in an edit to the question. – Flimm Sep 20 '16 at 14:26
  • I have `git config --global alias.ls ls-files --exclude-standard`, and that makes the answer to this question `git ls -i`. – jthill Jan 17 '18 at 17:51
  • @AlexanderBird You should update your answer to https://stackoverflow.com/a/12080920/812919 for the benefit of future readers if possible. – daka Jun 23 '18 at 00:03
  • Answers belong in **answers**, not in questions. Summarizing answers in the question means that voting, moderation, &c. on the answers themselves loses its value. – Charles Duffy Jan 05 '19 at 20:31
  • 1
    `git status --ignored` is the one I prefer: https://git-scm.com/docs/git-status#Documentation/git-status.txt---ignoredltmodegt – Eduardo Pignatelli Jul 07 '19 at 02:55

11 Answers11

759

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.


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.

VonC
  • 1,042,979
  • 435
  • 3,649
  • 4,283
  • @VocC, from my understanding of [these tests](https://github.com/Thr4wn/myths_about_git_show_all_ignored_files), The answer you recommend at the top simply can have big flaws. That's why I would normally recommend [riyad's answer](http://stackoverflow.com/a/1446609/10608) instead. – Alexander Bird Oct 26 '12 at 01:27
  • 3
    Since Git v2.13.2 Release: `git status --ignored` seems it also show untracked files: https://github.com/git/git/blob/master/Documentation/RelNotes/2.13.2.txt#L26-L27 – Pau Jun 23 '17 at 07:09
  • 1
    wow, `git check-ignore -v *` works great, as it shows where the config applied. Thank you. – Hoang Tran Jul 18 '17 at 16:53
  • @MikeD To make the **/* work (or actually, you can just do **) you need globstar to be set `shopt -s globstar` after that it should work. – Veda Jan 31 '18 at 10:17
  • Without enabling (risky) globstar: `git check-ignore -v $(find . -type f -print)` – rafi Jan 06 '20 at 15:49
  • @RafiB. Thank you. I have included your comment in the answer for more visibility. However, wouldn't that (the find command) include files from the `.git` subfolder as well? – VonC Jan 06 '20 at 15:56
  • `git ls-files -o -i --exclude-from...` does not include cached files, only `git ls-files -i --exclude-from...` (without -o) does. – honzajde Dec 01 '20 at 22:37
  • @honzajde Thank you for this feedback. I have edited the answer accordingly, and included your comment for more visibility. – VonC Dec 01 '20 at 22:40
551

There is a much simpler way to do it (git 1.7.6+):

git status --ignored

See Is there a way to tell git-status to ignore the effects of .gitignore files?

John Kugelman
  • 307,513
  • 65
  • 473
  • 519
Penghe Geng
  • 10,573
  • 3
  • 27
  • 39
  • 3
    What version of git are you using? Mine (1.7.0.4) says `error: unknown option 'ignored'`. Even adding `-s` as suggested in linked post didn't work. – Alexander Bird Oct 25 '12 at 21:49
  • 3
    My version is 1.7.6. Another version 1.7.5.1 is the one that requires `-s`. You may try `git status -h` to see if `--ignored` is supported – Penghe Geng Oct 26 '12 at 14:49
  • 1
    I guess that simply isn't supported yet in 1.7.0.4. My other computer has 1.7.9 and the --ignored flag is there – Alexander Bird Oct 26 '12 at 20:59
  • 4
    I tried every solution on this page. This is the best one. It shows both files and directories. This feature was probably not available back when this question was originally asked. (By the way, all of the solutions won't work properly with a brand new "git init" until you've at least staged changes.) – wisbucky Aug 30 '13 at 06:13
  • 14
    This is certainly much better than the accepted answer. It is also much safer than the `git clean -ndX` solution, because the rare situation when one mistakenly forgets the flags will have an irrevocable effect on the repository, since untracked files are deleted. So it is dangerous. On the contrary `git status --ignored` is always safe, even when erroneously typed and it's natural to remember. – Ioannis Filippidis Sep 15 '13 at 21:03
  • Unlike the other top answers, this one makes it possible to see the dot files in the output. Thanks! – Leksat Jan 31 '19 at 10:59
  • This solution worked on Windows. I recommend using `cmd` rather than PowerShell to run this. if you intend to read the output in the console as the dark red text is difficult to read on a dark blue background. – robyaw Mar 07 '19 at 12:37
  • Thank you, you saved me a lot of trouble. – Vladimir Sukanica Apr 03 '21 at 19:36
404

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.

ma11hew28
  • 106,283
  • 107
  • 420
  • 616
  • Nifty... however the reason I asked the original question was so that I could make sure that vendor files (*.dll) that were supposed to be there were... so deleting them would not be the desired result. HOWEVER: this is good to know as I have changed my strategy from ignoreing *.dll to ignoring my build output folder (but not my vendor folders). This would be a good alternative to `make clean` and very helpful on a build server. – Andrew Burns Feb 26 '10 at 16:56
  • 2
    I'm using git version 1.7.0.4, and the two commands ('git ls-files -o -i --exclude-standard', 'git clean -dXn') are not equivalent. The first show me 4 files, and the second only two. (.gitignore~, index.php~, sql/create_users.sql~, www/index.php~) (Would remove .gitignore~, Would remove index.php~). Am I missins something here? – Cesar Jun 15 '11 at 21:00
  • @VonC, sweet! Thanks! @Cesar, I'm not sure. I'm not so familiar with `git ls-files -o -i --exclude-standard`. `git clean -dXn` has always been what I wanted but doesn't show ignored files that have already been removed. `git ls-files -o -i --exclude-standard` might do that. So, that might be what's causing the difference. – ma11hew28 Jun 16 '11 at 01:09
  • 3
    One tiny thing - it might be a good idea to type the `n` first, less chance of accidentally deleting that way; `git clean -ndX` – Tobias Cohen Nov 24 '11 at 02:13
  • 1
    @TobiasCohen nice! I updated the answer with your suggestion. It's safer. Although, if you leave out the `n`, Git defaults to `fatal: clean.requireForce defaults to true and neither -n nor -f given; refusing to clean`. Still pretty safe, but typing the `n` first is even safer! :) – ma11hew28 Nov 26 '11 at 05:03
  • great tip, `git clean -nxdf` works best for me, I dont know the difference. – José F. Romaniello Feb 03 '14 at 13:37
  • @José the f has no effect if the n is specified. git clean -nxd, if you're happy with what it will remove then git clean -fxd to actually remove the files – Patrick McDonald Oct 12 '15 at 14:38
40

While generally correct your solution does not work in all circumstances. Assume a repo dir like this:

# ls **/*                                                                                                       
doc/index.html  README.txt  tmp/dir0/file0  tmp/file1  tmp/file2

doc:
index.html

tmp:
dir0  file1  file2

tmp/dir0:
file0

and a .gitignore like this:

# cat .gitignore
doc
tmp/*

This ignores the doc directory and all files below tmp. Git works as expected, but the given command for listing the ignored files does not. Lets have a look at what git has to say:

# git ls-files --others --ignored --exclude-standard                                                            
tmp/file1
tmp/file2

Notice that doc is missing from the listing. You can get it with:

# git ls-files --others --ignored --exclude-standard --directory                                                
doc/

Notice the additional --directory option.

From my knowledge there is no one command to list all ignored files at once. But I don't know why tmp/dir0 does not show up at all.

riyad
  • 439
  • 4
  • 3
  • 2
    This got me what I wanted, whereas the others did not (for my particular case)... thanks! It's frustrating to have to run two commands, but with an ignored directory, the --directory option at least finds me that, and I can pipe that into a find command to find the files. Thanks! – lindes May 26 '12 at 11:53
  • This does it all at once, and expands the directories: `(git ls-files -oi --exclude-standard; git ls-files -oi --exclude-standard --directory) | perl -nle '$seen{$_}++||next;if(-d){system"find",$_,"-type","f"}else{print}'` – Dee Newcum Jun 26 '12 at 20:14
17

Git now has this functionality built in

git check-ignore *

Of course you can change the glob to something like **/*.dll in your case

Git Reference

qwertymk
  • 30,576
  • 24
  • 107
  • 179
15

Here's how to print the complete list of files in the working tree which match patterns located anywhere in Git's multiple gitignore sources (if you're using GNU find):

$ cd {your project directory}
$ find . -path ./.git -prune -o -print \
| git check-ignore --no-index --stdin --verbose

It will check all the files in the current branch of the repository (unless you've deleted them locally).

And it identifies the particular gitignore source lines, as well.

Git continues to track changes in some files which match gitignore patterns, simply because those files were added already. Usefully, the above command displays those files, too.

Negative gitignore patterns are also matched. However, these are easily distinguishable in the listing, because they begin with !.

If you're using Windows, Git Bash includes GNU find (as revealed by find --version).

If the list is long (and you have rev), you can display them by extension (somewhat), too:

$ cd {your project directory}
$ find . -path ./.git -prune -o -print \
| git check-ignore --no-index --stdin --verbose \
| rev | sort | rev

For more details, see man find, man git-check-ignore, man rev, and man sort.

The point of this whole approach is that Git (the software) is changing rapidly and is highly complex. By contrast, GNU's find is extremely stable (at least, in its features used here). So, anyone who desires to be competitive by displaying their in-depth knowledge of Git will answer the question in a different way.

What's the best answer? This answer deliberately minimizes its reliance on Git knowledge, toward achieving the goal of stability and simplicity through modularity (information isolation), and is designed to last a long time.

MarkDBlackwell
  • 1,676
  • 17
  • 26
  • Much thanks! I had been struggling to figure out why some of my new source files occasionally have been missing from my commits. Turns out that I had a pattern: bin*, that I thought would match only names of files/directories starting with bin but instead it matches anything that includes bin in the full path of a file/directory! I guess, my problem comes from a misunderstanding of the precise semantics of pattern matching in .gitignore. Your 2-line script helped me find this mistake! – Nicolas Rouquette Nov 11 '15 at 22:10
14

It should be sufficient to use

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

as that covers everything covered by

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

therefore the latter is redundant.


You can make this easier by adding an alias to your ~/.gitconfig file:
git config --global alias.ignored "ls-files --others -i --exclude-standard"

Now you can just type git ignored to see the list. Much easier to remember, and faster to type.

If you prefer the more succinct display of Jason Geng's solution, you can add an alias for that like this:

git config --global alias.ignored "status --ignored -s"

However the more verbose output is more useful for troubleshooting problems with your .gitignore files, as it lists every single cotton-pickin' file that is ignored. You would normally pipe the results through grep to see if a file you expect to be ignored is in there, or if a file you don't want to be ignore is in there.

git ignored | grep some-file-that-isnt-being-ignored-properly

Then, when you just want to see a short display, it's easy enough to remember and type

git status --ignored

(The -s can normally be left off.)

iconoclast
  • 17,897
  • 10
  • 91
  • 122
  • This never worked for me, because you have to manually list those files. `git status --ignored` works on Debian sid but may be very new… but apparently it got added due to popular demand ;-) – mirabilos Sep 18 '13 at 14:16
  • 1
    By "works on Debian sid" I assume you mean "works with the version of Git installed by default on Debian sid"? You should really avoid letting yourself be held hostage by the versions of utilities included in your distro. You can upgrade them independently of the distro itself. – iconoclast Oct 24 '18 at 15:02
1

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:-.} | 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).

Top-Master
  • 2,934
  • 1
  • 17
  • 34
0

(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.

peterh
  • 9,698
  • 15
  • 68
  • 87
0

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.

cristianoms
  • 2,526
  • 2
  • 23
  • 26
-1

Assuming there are a few ignore directories, why not use "git status node/logs/" which will tell you what files are to be added? In the directory I have a text file that is not part of status output, e.g.:

On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
(use "git add ..." to include in what will be committed)

    node/logs/.gitignore 

.gitignore is:

*

!.gitignore

pikknz
  • 1
  • 1