有什么方法可以看到为什么一些文件被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-add'ed。在包含问题文件的目录中运行它:
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
git check-ignore -v filename
有关详细信息,请参阅手册页。
原答案如下:
Git目前还没有提供类似的功能。但在看到你的问题后,我在谷歌上搜索了一下,发现早在2009年,这个功能就被要求并部分实现了。在看完帖子后,我意识到要把它做好并不需要太多的工作,所以我已经开始了一个补丁的工作,希望能在接下来的一两天内完成。当这个答案准备好时,我会更新它。
更新:哇,这比我想象的难多了。git的排除处理的内部是相当神秘的。不管怎样,这里有一个几乎完成的提交系列,它适用于今天的上游主分支。测试套件已经完成了99%,但是我还没有完成——stdin选项的处理。希望这个周末我能做到,然后把我的补丁提交到git邮件列表中。
与此同时,我非常欢迎任何能够这样做的人进行测试-只需从我的git分支克隆,检查check-ignore分支,并正常编译它。
更新2:完成了!最新版本是在github如上所述,我已经提交补丁系列到git邮件列表进行同行评审。让我们看看他们是怎么想的……
更新3:经过几个月的黑客/补丁审查/讨论/等待,我很高兴地说,这个特性现在已经到达git的主分支,并将在下一个版本(1.8.2,预计2013年3月8日)中可用。这是检查忽略手册页。哇,工作量比我想象的要大得多!
更新4:如果你对这个答案如何演变以及该功能如何实现的完整故事感兴趣,请查看GitMinutes播客的第32集。
更新git 2.8(2016年3月):
GIT_TRACE_EXCLUDE=1 git status
参见“验证.gitignore文件的一种方法”
这是对下面描述的git check-ignore -v的补充。
原答案:2013年9月(git 1.8.2,然后是1.8.5+):
git check-ignore在git 1.8.5/1.9(2013年第四季度)中再次改善:
“git check-ignore”遵循与“git add”和“git status”相同的规则,即忽略/排除机制不会对已经被跟踪的路径生效。
使用"——no-index"选项,它可以用来诊断哪些应该被忽略的路径被错误地添加到索引中。
参见https://github.com/flashydave:中的commit 8231fa6
check-ignore currently shows how .gitignore rules would treat untracked paths. Tracked paths do not generate useful output.
This prevents debugging of why a path became tracked unexpectedly unless that path is
first removed from the index with git rm --cached <path>.
The option --no-index tells the command to bypass the check for the path being in the index and hence allows tracked paths to be checked too.
Whilst this behaviour deviates from the characteristics of git add and git status its use case is unlikely to cause any user confusion.
Test scripts are augmented to check this option against the standard ignores to ensure correct behaviour.
--no-index::
检查时不要查索引。
可以使用:
调试为什么一个路径被跟踪,例如git add。并没有像用户所期望的那样被规则忽略
当开发包含否定的模式以匹配之前用git添加的路径时,添加-f。
它可能不是。gitignore——3个可能被忽略的原因
文件可能会被忽略,原因如下:
.gitignore
Git update-index——skip-worktree
Git update-index——assume-unchanged
此外,如果一个文件在.gitignore中并且已经在索引/缓存中暂存,那么它可能会被unignore。
检查上述列举的情况:
对于.gitignore排除的两种情况,比较以下输出:
Git check-ignore——verbose——non-matching——no-index file1 file2 file3
Git check-ignore——verbose——不匹配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