Git命令可以显示哪些特定文件被.gitignore忽略。

841

我正在尝试使用Git,并遇到了以下问题:

我的项目源代码目录结构如下:

/
|
+--src/
+----refs/
+----...
|
+--vendor/
+----...
我在我的供应商分支中有代码(目前是MEF),我将在那里编译它,然后将引用移动到 /src/refs 中,这是项目从中获取它们的地方。
我的问题是,我已经将.gitignore设置为忽略*.dll*.pdb。 我可以执行git add -f bar.dll来强制添加被忽略的文件,这还好,但问题是我无法弄清楚如何列出已被忽略的文件。
我想列出已被忽略的文件,以确保我不会忘记添加它们。
我已经阅读了关于git ls-files的手册页面,但无法使其工作。 在我看来,git ls-files --exclude-standard -i应该做我想要的事情。 我错过了什么?

13
现在,您不会使用git-ls-files,而是使用“git ls-files”。 - wojo
7
请您考虑将riyad的回答标记为正确答案,因为这是唯一一个承认没有_保证_仅使用Git命令(包括git clean技巧)可以完成此操作的答案,正如 这里 所示。另外,我建议您不要在总结中使用“exclude-from”示例,因为这实际上没有注意任何.gitignore文件。我特别提出此请求,因为该页面是谷歌搜索的首要结果。 - Alexander Bird
答案应该放在答案中,而不是问题中。在问题中总结答案意味着对答案本身的投票、管理等失去了价值。 - Charles Duffy
8
我更喜欢使用 git status --ignored 这个命令:https://git-scm.com/docs/git-status#Documentation/git-status.txt---ignoredltmodegt - Eduardo Pignatelli
Qwertymk的回答就是最佳答案。git check-ignore -v [PATH] - meh
显示剩余5条评论
12个回答

951

注意:


也有趣的是(在qwertymk答案中提到),你也可以使用git check-ignore -v命令,至少在Unix系统上(在CMD的Windows会话中无法工作,但在Windows CMD git bash会话中可以工作)。
git check-ignore -- *
git check-ignore -v -- *

第二个显示了 .gitignore 的实际规则,该规则使文件在您的 git 存储库中被忽略。
在 Unix 上,使用 "What expands to all files in current directory recursively?" 和 bash4+:
git check-ignore **/*

(或者使用find -exec命令)
注意:https://stackoverflow.com/users/351947/Rafi B.评论中建议避免(有风险的)globstar
git check-ignore -v $(find . -type f -print)

确保从.git/子文件夹中排除这些文件。

CervEd评论中建议避免使用.git/

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

原始答案(2009年)
git ls-files -i

应该可以工作,除了它的源代码指出:
if (show_ignored && !exc_given) {
                fprintf(stderr, "%s: --ignored needs some exclude pattern\n",
                        argv[0]);

exc_given

原来在-i之后还需要一个参数才能真正列出任何内容:

尝试:

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

(但那只会列出您的缓存(非被忽略)对象,并带有过滤器,所以不完全符合您的要求)

例子:

$ 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

实际上,在我的“gitignore”文件(名为“exclude”)中,我找到了一个命令行,可以帮助你:
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]
# *~

所以....
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

应该能解决问题。

(感谢honzajde评论中指出git ls-files -o -i --exclude-from...不包括缓存的文件:只有git ls-files -i --exclude-from...(不带-o)才包括。)

ls-files手册页中所述,--others是重要的部分,用于显示非缓存的、非提交的、通常被忽略的文件。

--exclude_standard不仅仅是一个快捷方式,而是一种包括所有标准的“忽略模式”设置的方法。

exclude-standard
添加标准的git排除项:在每个目录中添加.git/info/exclude.gitignore文件,以及用户的全局排除文件。


3
自从 Git v2.13.2 版本发布以来:git status --ignored 命令似乎也会显示未跟踪的文件:https://github.com/git/git/blob/master/Documentation/RelNotes/2.13.2.txt#L26-L27 - Pau
1
哇,git check-ignore -v *非常好用,因为它显示了配置应用的位置。谢谢。 - Hoang Tran
@MikeD 要让 **/* 正常工作(或者实际上你可以直接使用 **),你需要设置 globstar 为 shopt -s globstar,之后它就应该能正常工作了。 - Veda
2
@CervEd 謝謝您的反饋,我已經按照 rafi 的建議進行了修改。為了更好的可見性,我已經將您的命令包含在答案中。 - VonC
1
@CervEd 好的,明白了。我已经编辑了答案,移除了“-type”参数。 - VonC
显示剩余17条评论

705

3
我的版本是1.7.6。另一个版本1.7.5.1需要使用"-s"参数。你可以尝试使用“git status -h”命令来查看是否支持“--ignored”参数。 - Penghe Geng
4
我已尝试此页面上的所有解决方案,这是最佳方案,它显示文件和目录。这一功能可能在最初提问该问题时并不可用。(顺便说一句,所有解决方案在使用全新的“git init”之前都不能正常工作,除非你至少提交了更改)。 - wisbucky
17
这绝对比被接受的答案好得多。它也比“git clean -ndX”解决方案更安全,因为如果错误地忘记了标志,就会对存储库产生不可撤销的影响,因为未跟踪的文件将被删除。所以是危险的。相反,“git status --ignored”始终是安全的,即使打错了也很容易记住。 - 0 _
这个解决方案在Windows上有效。我建议使用cmd而不是PowerShell来运行它,如果你打算在控制台中读取输出,因为深红色的文本在深蓝色的背景上很难读。 - robyaw
5
或者使用 git status --ignored --untracked-files=all 命令来显示被忽略的目录中的单个文件。 - Nicolas VERHELST

416
另一种相当简洁的选择(没有双关语):
git clean -ndX

解释:

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

注意:此解决方案不会显示已删除的已忽略文件。

2
我正在使用git版本1.7.0.4,而且这两个命令('git ls-files -o -i --exclude-standard','git clean -dXn')并不相等。第一个命令显示了4个文件,而第二个命令只显示了2个文件。(.gitignore〜,index.php〜,sql/create_users.sql〜,www/index.php〜)(将删除.gitignore〜,将删除index.php〜)。我错过了什么吗? - Cesar
@VonC,太好了!谢谢!@Cesar,我不确定。我对git ls-files -o -i --exclude-standard不是很熟悉。git clean -dXn一直是我想要的,但它不会显示已经被删除的被忽略文件。git ls-files -o -i --exclude-standard可能会做到这一点。所以,这可能是造成差异的原因。 - ma11hew28
3
一个小建议 - 先输入 n 字符可能是个好主意,这样就可以减少不小心删除的机会;git clean -ndX - Tobias Cohen
1
@TobiasCohen 不错!我已经采纳了你的建议更新了答案。这样更安全。虽然,如果你省略 n,Git 会默认为 fatal: clean.requireForce defaults to true and neither -n nor -f given; refusing to clean。仍然很安全,但是先输入 n 更加保险! :) - ma11hew28
1
@José 如果指定了n,则f没有影响。如果你对它将要删除的内容满意,那么使用git clean -fxd来实际删除文件。 - Patrick McDonald
显示剩余2条评论

44

虽然你的解决方案通常是正确的,但它并不适用于所有情况。假设有一个像这样的仓库目录:

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

doc:
index.html

tmp:
dir0  file1  file2

tmp/dir0:
file0

并且需要像这样的 .gitignore 文件:

# cat .gitignore
doc
tmp/*

这个命令忽略了doc目录和tmp目录下的所有文件。 Git正常工作,但是列出被忽略的文件的给定命令却不起作用。 让我们看看git的反应:

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

注意列表中缺少doc。 您可以使用以下命令获得它:

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

请注意增加了--directory选项。

据我所知,没有一个命令可以一次列出所有被忽略的文件。 但我不知道为什么tmp/dir0根本没有显示出来。


2
这让我得到了我想要的,而其他方法却没有(对于我的特定情况)...谢谢!虽然运行两个命令很烦人,但是通过忽略目录,--directory选项至少可以找到我需要的内容,并且我可以将其导入到find命令中以查找文件。谢谢! - lindes
这个命令可以一次性完成所有操作,并展开目录:(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

22

Git现在已经内置了这个功能

git check-ignore *

当然,你可以将glob更改为像** / *.dll 这样的内容。 Git参考

9
git check-ignore **/* 包括子目录中的文件。 - mzimmer
这仅列出顶级目录。 - Radon8472
很遗憾,内置的内容不是人类可读的,例如,它会列出vendornode_modules目录中的所有内容,请参见我的答案以获取可读性更好的版本:https://dev59.com/bHRB5IYBdhLWcg3w6bcE#66922010 - Top-Master

16

以下是如何打印出工作树中与 Git 的多个 .gitignore 文件中的任意模式相匹配的所有文件列表(如果您使用 GNU find):

这里有一个方法可以打印出工作树中与 Git 的多个 .gitignore 文件中的任意模式相匹配的所有文件列表(如果您使用 GNU find):

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

它将检查存储库当前分支中的所有文件(除非您已在本地删除它们)。

它还会识别特定的gitignore源行。

Git继续跟踪与gitignore模式匹配的某些文件的更改,仅因为这些文件已经添加过了。有用的是,以上命令也显示这些文件。

负面的gitignore模式也被匹配。但是,这些在列表中很容易区分出来,因为它们以!开头。

如果您正在使用Windows,Git Bash包括GNU的find(通过find --version可查看版本号)。

如果列表很长(且您有rev),您也可以通过扩展名来显示它们(在一定程度上):

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

更多详细信息,请参见man findman git-check-ignoreman revman sort

这种方法的重点在于Git(软件)正在快速变化并且非常复杂。相比之下,GNU的find非常稳定(至少在此处使用的功能方面)。因此,任何想要通过展示对Git的深入了解来竞争的人都会用不同的方式回答问题。

最好的答案是什么?这个答案故意尽可能地减少对Git知识的依赖,以实现通过模块化(信息隔离)来达到稳定性和简单性的目标,并被设计成可以持续很长时间


非常感谢!我一直在努力弄清楚为什么我的一些新源文件偶尔会从我的提交中消失。原来我有一个模式:bin*,我以为它只匹配以bin开头的文件/目录名称,但实际上它匹配包含bin的完整路径的任何文件/目录!我想,我的问题来自于对.gitignore中模式匹配的精确语义的误解。你的两行脚本帮助我找到了这个错误! - Nicolas Rouquette

15

使用这个应该足够了

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

因为它涵盖了所有被涵盖的内容

git ls-files --others -i --exclude-from=.git/info/exclude
因此,后者是多余的。


你可以通过在~/.gitconfig文件中添加别名来简化此过程:

git config --global alias.ignored "ls-files --others -i --exclude-standard"

现在你只需要输入 git ignored 就可以查看列表。记忆更容易,输入速度更快。

如果你喜欢 Jason Geng 的解决方案的简洁显示,你可以添加别名来实现:

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

然而,更加详细的输出对于排除.gitignore文件中的问题非常有用,因为它列出了每个被忽略的文件。通常你会通过使用 grep 命令来筛选结果,查看期望被忽略的文件是否在其中,或者不希望被忽略的文件是否在其中。

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

然后,当你只想看到一个简短的显示时,很容易记住并输入

git status --ignored

(通常可以省略 -s 参数。)


这对我从来没有起作用,因为你必须手动列出那些文件。git status --ignored 在 Debian sid 上可以工作,但可能非常新... 但显然是由于大众需求而添加的;-) - mirabilos
1
“在Debian sid上工作”是指“与Debian sid默认安装的Git版本兼容”吗?你真的应该避免让自己受到发行版中包含的实用程序版本的限制。你可以独立于发行版升级它们。 - iconoclast

5
如果你只需要一个有效的文件列表被忽略(不管它们是如何被忽略的),并且没有任何额外的通知和日志,那么请按照以下步骤操作:
一旦创建,无论在哪里(在Git-bash中)运行:
git ignore-list

执行以下命令创建:

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

注:

  1. 已在macOSWindows平台上测试并可用!
  2. 一旦你cd进入一个目录,仅列出从该目录(或其子目录)忽略的文件。
  3. 最后,始终记录相对于根目录(包含.git目录的目录,无论你cd进入哪个目录)的路径。

另一个有用的功能是人类可读性,例如如果整个目录被忽略,像buildnode_modules,这将仅记录目录名称。
git ls-files --others -i --exclude-standard 命令记录每个文件(适用于xargs)。


1

我只会这样做

git status --porcelain --ignored

并仅列出被忽略的文件

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

1
你可以使用 fd
运行的命令是:
comm -23 <(fd -HI | sort) <(fd -H | sort) 

请注意,如果没有.git目录,只有一个.gitignore文件(例如裸库),您必须明确告知.gitignore文件的位置。
comm -23 <(fd -HI | sort) <(fd -H --ignore-file .gitignore | sort)

更具体地说,请使用--no-ignore-vcs而不是-I 有关更多详细信息,请查看此处

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接