如何列出Git忽略的已暂存或已提交的文件?

94
如何获取已经提交或者暂存的与.gitignore规则匹配的文件列表?

可能是显示Git中被忽略的文件的重复问题。 - Cascabel
1
在其他问题的答案中,你要找的是 git ls-files -i --exclude-standard 或者可能是它的变体。 - Cascabel
13
据我所知,这不是显示Git中被忽略文件的问题 的重复。那个问题是询问如何列出未跟踪但被忽略的文件。而这个问题是询问如何列出已跟踪(因此豁免了忽略规则)但如果它们没有被跟踪将会被忽略的文件。 - Richard Hansen
4个回答

113

ls-files的文档并不十分清晰,但是似乎以下简单的别名可以完成任务:

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

上述命令创建了一个名为showtrackedignored的别名。要使用,请运行:
git showtrackedignored

它将列出当前目录和子目录中所有被跟踪但如果不被跟踪则会被忽略的文件。

git ls-files中的错误

不幸的是,这并不完全可靠。显然,Git能够很好地找到不应该被忽略的文件,但在搜索应该被忽略的文件(git ls-files-i选项)时,如果匹配忽略规则的目录,则不会列出该目录内被忽略的文件。

为了解决这个问题,请尝试转换您的忽略规则,使其仅匹配文件而不是目录(这并非总是可能的)。

(感谢Christoph发现此漏洞并向Git邮件列表报告!编辑:现在正在进行补丁工作,将包含在git 1.7.11.2或更高版本中)

替代方法

这是一种不同的方法。 它要复杂得多,可能会有破损的角落案例。

git config --global alias.showtrackedignored '!
cd "${GIT_PREFIX}" &&
untracked_list=$(git rev-parse --git-dir)/ignored-untracked.txt &&
git ls-files -o -i --exclude-standard >"${untracked_list}" &&
GIT_INDEX_FILE="" git ls-files -o -i --exclude-standard | grep -Fvxf "${untracked_list}" &&
rm -rf "${untracked_list}"'

该别名执行以下操作:
  • cd回到运行git showtrackedignored的目录(Git从顶级目录而不是当前目录运行基于shell的别名;请参见git help config中关于alias.*的部分)
  • 定义一个名为untracked_list的变量。此变量保存指向包含当前被忽略文件列表的临时文件的路径。此临时文件位于.git目录中。
  • 将被忽略的文件列表写入${untracked_list}
  • 告诉Git假装索引为空并列出所有被忽略的文件。
  • 将该输出传输给grep,过滤掉写入${untracked_list}的文件。
  • 删除临时文件${untracked_list}

这种方法的缺点:

  • 它在您的.git目录中创建了一个临时文件。
  • 它假定您拥有一个符合POSIX的shell。
  • 它假定您拥有一个符合POSIX的grep实现。
它也遭受了与前一个别名相同的错误。

最近git有没有进行过更改,导致这个脚本出现了问题?自从我发现它以来,一直运行得非常好,但最近我发现它无法发现所有已提交但与忽略模式匹配的文件/文件夹(或者可能只是文件夹)。我使用的是git 1.7.9.5版本。有什么想法吗? - Christoph
1
@Christoph:在我的Linux(Ubuntu)上,1.7.10版本可以正常运行。尝试手动分别运行每个命令,以查看脚本的哪一部分出现了问题。如果您找到了问题,请告诉我,我会更新我的答案。此外,如果您能创建一个展示问题的示例存储库,请让我知道。谢谢! - Richard Hansen
1
@Christoph:git help ignore中写道:“foo/将匹配目录foo及其下面的路径”。显然,“其下面的路径”部分在Git试图识别未被忽略的文件时有效,但在Git试图识别已被忽略的文件时则无效。 - Richard Hansen
2
现在,git ls-files -i --exclude-standard 是一个更加干净和正确的方法。我有一个存储库,在那里传统的别名会给出错误的结果。 - Christoph
1
@Christoph:谢谢,我编辑了答案,将更简单的方法放在了前面,并添加了对于复杂方法的警告。 - Richard Hansen
显示剩余7条评论

26

只是在这里留下一个,基于Richard的答案:

git ls-files --cached -i --exclude-standard

删除每个被.gitignore忽略的已跟踪文件:

git ls-files --cached -i --exclude-standard | xargs git rm --cached


9
如果有人只想列出文件(按照原帖问题),而不一定要删除,但很快就可以复制粘贴,则此代码是危险的!也许把它写成两行比较好? - Matifou
要在路径中带有空格的存储库上运行此操作,请使用以下的空值分隔的输入/输出: git ls-files -z --cached -i --exclude-standard | xargs -0 git rm --cached-z 告诉 git-ls-files 以 null 终止符输出每个路径,在管道的 xargs 端使用 -0 进行镜像。 - Jules Kerssemakers

0
其他答案只显示当前被忽略但存在于工作树/索引中的文件。
要查看当前被忽略但过去已经提交(可能已删除)的文件。
git log --pretty=format: --name-only --diff-filter=A `# all files ever` \
| sed '/^$/d' `# skip git-logs empty lines` \
| sort -u `# sort + unique` \
| tr '\n' '\0' `# null separate for xargs` \
| xargs -0 git check-ignore # check if they are ignored

不确定重命名的文件是否会显示多次。

编辑:

修复格式并跳过git-log中的空行。


-3

那个命令会列出未被追踪的文件和目录,如果去掉 d 参数,它还会列出已暂存和已提交的未被追踪文件。但我认为这并没有真正回答问题。 - Hedgehog
@Hedgehog:这是一个重复问题,但是seth从中选择了错误的答案。 - Cascabel
我并不否认它们在同一个邻域,但是从观察到的事实来看,它们不是重复的问题似乎是很清楚的,因为不清楚哪个(如果有的话)答案能够精确地做到这一点。Show ignored files in git中的问题是“列出存在但被忽略的文件”。 - Hedgehog

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