解释哪个 gitignore 规则忽略了我的文件

Posted

技术标签:

【中文标题】解释哪个 gitignore 规则忽略了我的文件【英文标题】:Explain which gitignore rule is ignoring my file 【发布时间】:2012-08-22 02:20:36 【问题描述】:

有什么方法可以查看为什么某些文件被 git 忽略(即 .gitignore 文件中的哪个规则导致文件被忽略)?

想象一下我有这个(或者更复杂的场景,有数百个文件夹和数十个 .gitignore 文件:

/
-.gitignore
-folder/
    -.gitignore
    -subfolder/
              -.gitignore
              -file.txt

如果我运行git add folder/subfolder/file.txt git 可能会抱怨它被忽略:

The following paths are ignored by one of your .gitignore files:
folder/subfolder/file.txt
Use -f if you really want to add them.

有什么方法可以知道所有可能的.gitignore 中有一个规则可以忽略此文件并显示该规则?喜欢:

The following paths are ignored by your folder/.gitignore file (line 12: *.txt)
folder/subfolder/file.txt
Use -f if you really want to add them.

或者只是:

$ git why-is-ignored folder/subfolder/file.txt
folder/.gitignore:12:*.txt

【问题讨论】:

注意:git check-ignore 很快 (git1.8.5/1.9) 将有一个 --no-index 选项。见my answer below 注意:GIT_TRACE_EXCLUDE=1 git status 很快将成为调试.gitignore 规则的另一种方式。见my edited answer below 相关博文:danielcompton.net/2016/04/21/…. 【参考方案1】:
git check-ignore -v filename

更多详情请见the man page。

原答案如下:

git 目前不提供类似的东西。但在看到你的问题后,我做了一些谷歌搜索,发现早在 2009 年this feature was requested and partially implemented。读完帖子后,我意识到正确地完成它不会有太多的工作,所以我已经开始着手开发一个补丁,希望在接下来的一两天内完成。准备好后,我会更新此答案。

更新:哇,这比我预期的要难得多。 git 的排除处理的内部结构非常神秘。无论如何,这里的an almost finished series of commits 适用于今天的上游master 分支。测试套件已完成 99%,但我还没有完成对 --stdin 选项的处理。希望这个周末我能解决这个问题,然后将我的补丁提交到 git 邮件列表。

与此同时,我绝对欢迎任何能够这样做的人进行测试 - 只需从 my git fork 克隆,检查 check-ignore 分支,然后正常编译即可。

更新 2: 完成了!如上所述,最新版本在 github 上,我有 submitted the patch series to the git mailing list 供同行评审。让我们看看他们的想法......

更新 3: 经过几个月的黑客/补丁审查/讨论/等待,我很高兴能够说this feature has now reached git's master branch,并将在下一个版本中提供 ( 1.8.2,预计 2013 年 3 月 8 日)。这是check-ignore manual page。唷,这比我预期的要多得多!

更新 4:如果您对有关此答案如何演变以及该功能如何实施的完整故事感兴趣,请查看 episode #32 of the GitMinutes podcast。

【讨论】:

我使用的是 1.8.2 而git check-ignore 什么也没做。 @yourfriendzak 毫无疑问,git check-ignore 存在并在 1.8.2 中工作。如果行为不是您所期望的,我建议您(重新)阅读手册页,如果仍然不是,请在 git 邮件列表上提交适当的错误报告。只是说它没有做任何事情并不是很有帮助。我希望您可能已经在一个未被忽略的文件上运行它并且错误地期望一些输出(尽管将来我可能会在--verbose 输出模式中添加对--show-unmatched 的支持)。 @AdamSpiers 你是对的。我应该指定当我执行命令时,什么都不打印。没有错误消息,没有成功消息,没有信息。就在下一个空白提示出现。那么我是否正确地假设在某些情况下“没有输出”是预期的行为? @AdamSpiers 非常感谢您!经过 3 天的调查,您刚刚帮助我找到了由于 .gitignore_global 中的全局忽略文件而导致构建中断的原因!我什至不知道这是一件事! 并不是每天都能看到 Stack Overflow 开发人员为了实现开发人员功能而进行如此多的更改。哇,尊重。【参考方案2】:

更新 git 2.8(2016 年 3 月):

GIT_TRACE_EXCLUDE=1 git status

见“A way to validate .gitignore file”

这是对下面描述的git check-ignore -v 的补充。


原始答案:2013 年 9 月(git 1.8.2,然后是 1.8.5+):

git check-ignore 在git 1.8.5/1.9 (Q4 2013) 中再次改进:

git check-ignore”遵循与“git add”和“git status”相同的规则,因为忽略/排除机制不会对已跟踪的路径生效。使用“ --no-index" 选项,它可以用来诊断哪些应该被忽略的路径被错误地添加到索引中

从https://github.com/flashydave看到commit 8231fa6:

check-ignore 当前显示.gitignore 规则将如何处理未跟踪的路径。跟踪的路径不会产生有用的输出。 这可以防止调试路径被意外跟踪的原因,除非该路径是 首先使用 git rm --cached <path> 从索引中删除。

--no-index 选项告诉命令绕过对索引中路径的检查,因此也允许检查跟踪的路径。

虽然这种行为偏离了git addgit status 的特征,但它的用例不太可能引起任何用户混淆。

增加了测试脚本以根据标准忽略检查此选项,以确保正确的行为。


--no-index::

进行检查时不要查看索引。 这个可以用:

调试路径被例如跟踪的原因git add . 并且没有被用户预期的规则忽略或 在开发包括否定的模式以匹配先前添加 git add -f 的路径时。

【讨论】:

【参考方案3】:

可能不是.gitignore -- 3 个可能的忽略原因

文件可能会因为以下原因而被忽略:

    .gitignore git update-index --skip-worktree git update-index --assume-unchanged

此外,如果文件位于 .gitignore 并且已经暂存在索引/缓存中,则该文件可能会被 UNignored by。

检查上面列举的情况:

    对于.gitignore排除的两种情况,比较输出:

    git check-ignore --verbose --non-matching --no-index file1 file2 file3 git check-ignore --verbose --non-matching file1 file2 file3

    git ls-files file1 file2 file3 | grep -E '^S'

    git ls-files file1 file2 file3 | grep -E '^[[:lower:]]'

太难了,给我一个别名!

以下别名将涵盖上面列出的所有情况:

ignore = !"bash -c 'diff --unified=999999999 --color=always <(echo a; git check-ignore --verbose --non-matching --no-index . \"$@\") <(echo b; git check-ignore --verbose --non-matching . \"$@\")' - \"$@\" | tail -n+7; git hidden \"$@\" # Show ignore status of arguments. Files included by index are tagged with prepended '+'."
hidden = !"git ls-files -v -- \"$@\"| grep -E '^(S|[[:lower:]])' # S means update-index --skip-worktree, and lower first letter means --assume-unchanged."

注释和结尾" 是要复制到您的.gitconfig 的行的一部分。

用法:

git ignore file1 file2 file3

【讨论】:

【参考方案4】:

我在手册页中找不到任何内容,但这里有一个快速而肮脏的脚本,它将检查您在每个父目录中的文件,看看它是否可以被 git-add。在包含问题文件的目录中运行:

test-add.sh STOP_DIR FILENAME

其中STOP_DIR 是Git 项目的***目录,FILENAME 是问题文件名(没有路径)。它在层次结构的每个级别创建一个同名的空文件(如果它不存在)并尝试git add -n 以查看是否可以添加它(它会自行清理)。它输出如下内容:

FAILED:    /dir/1/2/3
SUCCEEDED: /dir/1/2

脚本:

#!/usr/bin/env bash
TOP=$1
FILE=$2
DIR=`pwd`
while : ; do
  TMPFILE=1
  F=$DIR/$FILE
  if [ ! -f $F ]; then
    touch $F
    TMPFILE=0
  fi
  git add -n $F >/dev/null 2>&1
  if [ $? = 0 ]; then
    echo "SUCCEEDED: $DIR"
  else
    echo "FAILED:    $DIR"
  fi
  if [ $TMPFILE = 0 ]; then
    rm $F
  fi
  DIR=$DIR%/*
  if [ "$DIR" \< "$TOP" ]; then
    break
  fi
done 

【讨论】:

【参考方案5】:

添加到使用git check-ignore -v filename 的主要答案(谢谢顺便说一句) 我发现我的 .gitignore 文件阻止了所有内容,因为通配符后面有一个换行符,所以我有:

* .sublime-project

例如。我刚刚删除了换行符,瞧!它已修复。

【讨论】:

【参考方案6】:

上下文:我遇到了一个非常相似的问题,我找不到忽略我的文件/文件夹的规则。我试过 git check-ignore -v filename但它没有给我任何结果,或者结果是我的 .gitignore 文件中有一个带有空白行的行号。所以问题是我的文件没有被我忽略本地 .gitignore 文件,但由我的本地 core.excludes 文件(未包含在我的存储库中)。

解决方案:我使用以下命令查找文件的位置:git config core.excludesfile然后我打开它并删除有问题的行,就是这样。

参考:您也可以查看here 以获得更多说明。

【讨论】:

以上是关于解释哪个 gitignore 规则忽略了我的文件的主要内容,如果未能解决你的问题,请参考以下文章

.gitignore non-valiate

Git 忽略规则 .gitignore文件

Git忽略规则和.gitignore规则不生效的解决办法

Git忽略规则及.gitignore规则不生效的解决办法

Git忽略规则和.gitignore规则不生效的解决办法

Python - Git仓库忽略提交规则 & .gitignore配置