What to do if you accidentally committed your node_modules
Tags: npm, git, github, beginners
Published: 2020-08-06 13:49:04

So here you are, npm installing stuff, happily committing code in your project. Things are going well! While looking up a tricky bit of syntax, you stumble across the following advice: _Don't commit your node_modules!_ 

### Why don't you commit them?

You don't need to track automatically generated files like `node_modules`, which are the front end dependencies listed in your project's `package.json`. Running `npm install` will create (or update) `node_modules`. There's no reason for these packages to be in version control, since npm can manage them for you. 

### But I already committed them 😕

If you have already mistakenly committed these files, you need a way to tell git that you don't want to track them anymore. But you still want to keep them in your project, since they contain code that your project depends on. 

With git, there is (almost) always a way! Just follow these steps to get your repo in order.

## Tell git to ignore `node_modules`

Git will exclude any files or directories listed in the aptly named `.gitignore` file, so changes to files listed there will be treated as if they don't exist. Our first step is making sure `node_modules` is on the gitignore list.

If you don't have a gitignore file, now's a great time to make one! You can get ready-made, project-specific contents at [gitignore.io] (https://www.toptal.com/developers/gitignore), but you can make a new empty file now and add more to it later.

For all the following commands, you'll need to use the command line (don't type the `$`; that just indicates the command line prompt).

If you need to, create a gitignore file at the project root:
```
$ touch .gitignore
```

Open `.gitignore` in your code editor and add the name of the directory you don't want git to track, anywhere in that file:
```
# anywhere in .gitignore
node_modules
```
This is a _pattern_ for git to match, not a _path_, so it will ignore any file or directory in your repo named 'node_modules'.

Go ahead and add the gitignore file to be committed. We definitely want other project contributors not to track `node_modules`.
```
$ git add .gitignore
```

If you had not already committed `node_modules`, this step would be all you need. You could go ahead and commit the changes and you'd be done.


## Remove the files from git's index 

If you committed `node_modules` before they were added to the gitignore file, git is going to notice changes each time you add and install a new package, when the `node_modules` directory changes. So we need one more step to seal the deal.

```
$ git rm -r --cached node_modules
```

What you will see now if you check `git status` is that any files in `node_modules` that were shown in red are now in green. This means that they are staged in git. They are also marked as `deleted`. 

#### Details of what this command does

- `rm` is a [git command](https://git-scm.com/docs/git-rm) that tells git to stage the removal of the file from tracking.
- `-r` is an option that tells git to perform the `rm` command recursively. A recursive operation is necessary because we have a directory that contains other files and other directories, so we have to dig into each of those to delete all of them.
- `--cached` refers to git's cache, also called the _index_, where changes to files can be staged for committing. This option ensures that _we are not deleting the files themselves_, only removing the reference to their changes.
 
Now we need to commit our changes. This commit will include our `.gitignore` addition from the previous step. 

```
git commit -m "Remove and ignore node_modules"
```

And now, huzzah! 🎉 Your project dependencies are still intact, but `node_modules` will no longer show up in your git index when they change. You can safely push this commit to GitHub, where you will no longer see a `node_modules` directory in your project. That's what we want!

## This works with any other files you've accidentally committed

You can use these same steps for anything else that you accidentally commit. Add the file to your `.gitignore`, then use `git rm --cached <filename>` to stage the deletion of the file from the index. For example:

```
$ git rm -r --cached static/js/webpack_bundles
$ git rm --cached webpack-stats.json # if it's a file, you don't need the recursive option
```

### Take extra steps to deal with sensitive information  

It's important to note that `git rm` will remove files in current and future commits, but _will not remove them from the history_. This usually doesn't pose a problem, but if you've accidentally committed a file that should be erased from history because it contains sensitive information (like API keys or credentials for services like AWS), consult [GitHub's comprehensive guide on what to do](https://docs.github.com/en/github/authenticating-to-github/removing-sensitive-data-from-a-repository).

## Why all the fuss, git? 

Git's whole purpose is to track what has changed in your project. When a file gets created in a git repo, you have to explicitly tell git to start tracking that file in the first place. For a complete record of what has happened in the course of project development, we _also_ want to record when those files are deleted or no longer tracked. That is what we use `git rm` to do and why a commit is made. It's just another bookmark in the history.