git add adding ignored files

I'm trying to remove a previously tracked directory from git, which works, but it's being added back with each subsequent git add ., git add -A, etc. Here's what I've done:

Add to .gitignore in root of project:

node_modules

Run the following:

git rm -r --cached node_modules
git commit -a -m "removed node_modules"
git push origin master

So far so good, this removes the directory from the remote repository. The problem is when I later run git status it tells me the node_modules directory is untracked and keeps adding it back on future commits.

What am I missing and/or how do I find the root of my problem?

From here:

The git add command will not add ignored files by default. ... The git add command can be used to add ignored files with the -f (force) option.

Additional information from comments:

I am tracking .gitignore file.

git check-ignore node_modules/ returns node_modules/ as expected.

No use of submodules.

Update:

I've created a sample that appears to replicate the issue following the steps above:

https://github.com/awhitehouse104/SampleRepo

Resolution:

To summarize the answer and comments from below, the issue was in the encoding of my .gitignore file. I had used echo 'node_modules' > .gitignore to create the file on windows 8 and it came out as UTF-16 with BOM (according to answer below). After a few google searches, it seems this is the default encoding with powershell and I can confirm that saving as UTF-8 seems to have resolved the issue.

tldr; Probably don't use this method of creating .gitignore files or be prepared to change the encoding

echo 'node_modules' > .gitignore


You probably have a negative rule (include-again rule, the one that starts with an !) in your .gitignore file somewhere after the node_modules line.

git check-ignore has a bug/ambiguity in the docs. You expect that if git check-ignore node_modules/ prints node_modules/, then node_modules/ is ignored. But actually it prints a pathname if that pathname matches any ignore pattern - positive or negative. The only way to be sure is to use the -v (--verbose) option, which will make git check-ignore print the matching pattern.
Moreover, if git check-ignore -v says a directory is ignored, it doesn't necessarily mean that all files in that directory are ignored. Example repo:

/
    .git/
    .gitignore
    node_modules/
        bar
        foo
$ cat .gitignore 
/node_modules/*
!/node_modules/foo

$ git check-ignore -v node_modules/
.gitignore:1:/node_modules/*    node_modules/
             ^ positive pattern => ignored

$ git check-ignore -v node_modules/foo
.gitignore:2:!/node_modules/foo node_modules/foo
             ^ negative pattern => not ignored

$ git add -A

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   node_modules/foo
#

So if git check-ignore -v node_modules/ says node_modules/ is ignored, do git add -A node_modules/ and then run git check-ignore -v --no-index against individual files that got added, to discover why they were added.


Update: I didn't expect that: your .gitignore file is in "UTF-16 with BOM (byte order mark)" encoding:

$ cat .gitignore | hexdump -vC
00000000  ff fe 6e 00 6f 00 64 00  65 00 5f 00 6d 00 6f 00  |..n.o.d.e._.m.o.|
00000010  64 00 75 00 6c 00 65 00  73 00 0d 00 0a 00        |d.u.l.e.s.....|

That's why git probably can't handle it. Save the file in UTF-8 without BOM, that should fix the problem. But I also suggest filing a bug report against git check-ignore - in this corner case its output is clearly not consistent with what git actually ignores.


Add the file to git ignore, then

git update-index --assume-unchanged <file>

You can do

git check-ignore -v --no-index path/with/unexpected/result

to see why git add did or didn't add that path.

git check-ignore docs.

In particular, the point is you want to check what's actually getting added, not a directory.

further, do find . -name .git. Submodules are nested repos, .gitmodules and the submodule command are handy but they're just there to help with them.


Here is what I do to ignore node_modules folder after I tracked it.

  1. Create the .gitignore file and add node_modules to it.

  2. Commit the .gitignore file. After this point, whatever you update in the node_modules folder won't appear in git status.

  3. But this does not delete what we already have on the repo under the node_modules folder. So now we need to remove whatever we have committed previously.

    For this, use git rm --cached node_modules -r

  4. Now git status will show that the files are deleted.

  5. Use git commit -m "node_modules removed" command with any message.

Now everything should be removed from the repo and future changes will not be tracked.