有什么方法可以看到为什么一些文件被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
它可能不是。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
我在手册页中找不到任何东西,但这里有一个快速和肮脏的脚本,它将检查每个父目录下的文件,看看它是否可以被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
它可能不是。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
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集。