从 gitignore 过滤文件和路径

filtering of files and paths from gitignore

我想使用 C# 找到所有 未被 .gitignore(或子目录中任何嵌套的 .gitignore 文件)过滤的文件路径。这类似于 question here 关于 PHP。我想知道是否有人知道这段代码是否已经在网上某个地方可用(在 C# 中)。

更新:回答我想要这个的目的,这样我就可以 运行 我自己对某些项目的源文件进行小的定期备份(压缩结果),让我更加安心。困难的部分是获得一个健壮的 .gitignore 解析器来获取过滤后的文件路径(并排除其他路径),如果其他人已经为我完成了它,又不想过于卷入学习该规范。

如果不知道你想对列表做什么(在构建脚本中使用它,以某种方式处理文件,只需在 UI 上查看它们等),就很难提出建议。

我在 C# 中找不到,但是 this JavaScript gitignore parser 没有很多代码可以转换,它公开了一个 accepts 和一个 denies 方法来获取包含或忽略文件的列表。它有很好的文档记录,有测试,它使用的正则表达式在 C# 中的工作与在 JavaScript.

中一样好。

This answer 可以在 C# 中运行,前提是您在 C# 代码为 运行.

的计算机上安装了 Git

另请注意,Visual Studio 的 Git Source Control Provider 插件在 IDE 中提供了正确的列表,以及复选框和将某些文件一起提交的功能以及许多其他功能在命令行上难以实现的功能。

NOTE: The Git Source Control Provider is open source (written in C#) and you can view the source here, but it may be much more involved to reverse engineer than the JavaScript project.

嗯,解析 .gitignore 文件(以及 Git 使用的其他文件,例如 $GIT_DIR/info/exclude)的最佳方法是让 Git 为你。 :-)(在您的情况下,实际上大多数情况下,这确实涉及执行 git 子流程。)

git check-ignore

git check-ignore 命令可用于检测哪些文件被忽略以及原因。 --non-matching 选项使它告诉您有关未被忽略的文件的信息,但由于它仍然会告诉您有关被忽略的文件的信息,并且采用特殊格式,因此您需要做一些进一步的工作获取未忽略文件的简单列表。这个 Bourne shell 函数可以解决问题:

find_nonignored() {
    find . -path ./.git -prune -o -print \
        | git check-ignore --verbose --non-matching --stdin \
        | sed -n -e 's,\t./,\t,' -e 's,^::\t*,,p' \
}

工作原理

find 命令查找当前工作目录中及以下的所有文件,这些文件应该位于您要过滤的树中的某处。我们从输出中排除顶级 .git 子目录及其下的所有内容(如果存在); /.git/ 不在典型的 .gitignore 文件中,因为 Git 会自动忽略它,因此通常被 git check-ignore.

视为 "not ignored"

git check-ignore 将仅在 --verbose 模式下打印出 --non-matching 文件,因为它仅在该模式下打印出额外信息,告诉您文件是否被忽略或不是。 (它总是打印被忽略的文件。)路径每行一个,格式为

source:linenum:pattern<TAB>path

冒号分隔的字段是有关导致路径被忽略的原因(例如 .gitignore 文件中的一行)的信息,如果文件未被忽略,则为空。

sed 命令然后过滤输出以仅显示被忽略文件的路径。 -n 选项告诉它默认不打印输入行。第一个替换模式仅将 <TAB>./ 替换为 <TAB>,移除前导 ./,纯粹出于美学原因。第二个替换完成真正的工作,删除任何开始一行的 ::<TAB>(表示没有 "ignore" 信息),如果发生替换,则打印该行的剩余部分,即未忽略的路径。

您可以进一步过滤以进行额外处理;我为一个脚本构建了这个,它按照这些行进行降价检查:

markdownlint $(find_nonignored | grep '\.md$')

备注

  1. 此代码在输出中包含未跟踪的文件(即从未添加到 Git 存储库或暂存的文件),这通常是您想要的。 (例如,测试系统仍然应该检查新文件,甚至在它们具有 git add 运行 之前。)请注意涉及 git ls-files 等的其他解决方案通常不会这样做这个.

  2. 以上代码依赖于使用 GNU sed,它将 \t 解释为一个选项卡。如果您使用 BSD sed(例如在 MacOS 上),您可能需要稍微调整一下。查看评论,看看是否有人对此有提示。

  3. 此处的所有代码都在带有空格或其他 "unusual" 字符的路径上中断;它需要在几个地方进行修改(例如使用 -print0find)来解决这个问题。为了使解释简单,我不在这里解决此类问题。我还为其他人留下了在任意路径上工作的函数的泛化,而不仅仅是当前工作目录。

对于那些正在寻找 C# 库的人,您也可以检查一下。

.gitignore based parser implemented in C# according to the .gitignore spec 2.29.2. The library is tested against real git status outputs. The tests use LibGit2Sharp for that.

https://github.com/goelhardik/ignore

它是其他开源库的一个端口,目前看来它对我的其他项目也很有效。