If a .gitignore contains a ! entry, git check-ignore will still say the matching file is ignored if the file is not in the index. Simple case to reproduce: $ git init . $ echo "*.c" > .gitignore $ echo '!a.c' >> .gitignore $ touch a.c b.c $ git check-ignore a.c b.c a.c b.c $ git add *.c The following paths are ignored by one of your .gitignore files: b.c Use -f if you really want to add them. $ git check-ignore a.c b.c b.c $ git check-ignore --no-index a.c b.c a.c b.c $ git check-ignore --no-index --verbose a.c b.c .gitignore:2:!a.c a.c .gitignore:1:*.c b.c In looking through check-ignore.c, it appears that we check that last_exclude_matching() returns an exclude object. It should be noted that we do not consider that exclude struct can be set with the EXC_FLAG_NEGATIVE flag. This flag says that the final matching rule should not be ignored. check_ignore needs to consider this condition in order to work properly.