我正在维护一些git pre-commit挂钩,并且我一直想为所有或者应该受版本控制的文件做些什么。
了解项目结构可以让我做得很好,但有关构建系统输出目录,测试日志文件和编辑器粪便的所有信息都已在.gitignore
中。
是否有一种简单的方法可以根据文件路径是否与.gitignore
中的模式匹配来过滤文件路径。
喵,我可以在
中替换WHAT GOES HERE
find "$(git rev-parse --show-toplevel)" --my --filters | WHAT GOES HERE
这样我就可以获得与我的过滤器匹配的所有且只有非gitignored文件。
我认为我可以通过
获得一个负面过滤器,我可能会comm
进入... | xargs git ls-files -X .gitignore -i
race
但我希望一步到位。
答案 0 :(得分:2)
更新 - 如对此答案的评论交换中所述,check-ignore
命令表示它列出了忽略的文件,但是如果您忽略了规则包括异常(以!
开头的模式),即使文件未被忽略,也会打印与这些模式匹配的文件。虽然一些文档可以被理解为描述这种行为,但同一文档的其他部分强烈暗示它不是什么意思 - 所以我认为它是一个错误,但不管这些解释如何,它和#39;软件是如何工作的。
所以...如果你不使用!
模式,下面的工作方式就像宣传的那样。如果你做使用!
模式,那么你可以通过使用--verbose
输出和后处理来查看匹配模式是包含还是排除。< / p>
使用ls-files
获取所需的确切行为可能并不像看起来那么容易。首先,您可能不是-i
,因为仅列出忽略的文件...
但无论如何,一种不同的(更多&#34;一步&#34;)方法将是:
在find
命令中,您可以使用-exec
操作为与其他过滤器匹配的每个文件调用git check-ignore
。
find "$(git rev-parse --show-toplevel)" <filters> -not -exec git check-ignore -q {} \; <actions>
这将正确解释所有来源的忽略规则。
默认情况下,这也意味着如果文件在索引中,则不显示为&#34;排除&#34;即使它在.gitignore
,中反映了忽略规则的真实行为。
但是如果您不想处理与忽略模式匹配的文件,即使它们在索引中并且因此并未真正被忽略,您可以修改命令来执行此操作:
find "$(git rev-parse --show-toplevel)" <filters> -not -exec git check-ignore -q --no-index {} \; <actions>
由于您从使用find
开始,我假设您只关心工作树中当前存在的文件。
您可能还想排除.git
目录。如果.git
是唯一的&#34;点文件&#34;在您的顶级目录中,您可以说
find "$(git rev-parse --show-toplevel)"/* <filters> -not -exec git check-ignore -q --no-index {} \; <actions>
如果你不能做出这个假设,那么你可以
find "$(git rev-parse --show-toplevel)" -path "$(git rev-parse --show-toplevel)"/.git -prune -o <filters> -not -exec git check-ignore -q -no-index {} \; <actions>
由于对rev-parse
的两次调用,这有点难看。您可以在运行rev-parse
之前将find
结果捕获到环境变量,但这可能会导致您的&#34;一步&#34;偏爱。另一个选项是,如果您可以安全地忽略名为.git
find "$(git rev-parse --show-toplevel)" -path */.git -prune -o <filters> -not -exec git check-ignore -q -no-index {} \; <actions>