Removing Ignored Files From a Git Repository

Earlier this week I was asked to review a few pull requests on an older project. The project maintainer wasn’t available and the client was anxious to have the changes deployed. A cursory glance at the pull requests revealed conflicts. All on files generated by the build process.

The project was started after we had only recently made the transition from Subversion to Git. Whoever created the project was new to Git and didn’t properly understand how to use the .gitignore file.

Starting Out

When you initialise an empty Git repository using git init the newly created repository will contain no .gitignore file. That’s not so bad for simple projects. However if any part of your project will be compiled then you’ll most likely need to create one.

Templates

GitHub’s gitignore repository provides an extensive collection of templates targeting various languages and environments. It provides an easy way to get started and is updated often.

This repository populates the add .gitignore drop down list on GitHub’s create a new repository page so you may already be familiar with it.

Documentation

Having a good starting point is useful but what about knowing how and when to update it? Only basic projects will be covered entirely by a template.

If you’re unfamiliar with how .gitignore files work there is detailed documentation available.

Stop Tracking

Git will continue to track changes to files which have previously been committed. Even if your new .gitignore file excludes them. There are a few steps to correct this.

Remove Files From Index

To stop Git tracking the unwanted files we must remove them from the index. There are a number of ways we can approach this.

Individualy

You can stop tracking an individual file by using the following command.

git rm --cached <file>

The --cached option causes the file to be removed from the index but not from the working tree.

Rebuild the Index

This approach involves removing everything from the index and then adding everything again while respecting the .gitignore file. A drawback of this method is that any untracked files will also be added.

git rm -r --cached .

The -r option means that files and folders will be removed recursively. The . represents the current working directory. After executing this command the index will be empty.

git add .

Adding the current working directory will cause git to re-add all the files which are not excluded by the .gitignore file.

I read about this approach from an answer by Matt Frear on Stack Overflow.

List and Remove

My preferred method is to list all the files which the updated .gitignore file would exclude and then remove those files from the index. Quick and precise.

git ls-files --ignored --exclude-standard | xargs git rm --cached

When combined with the --ignored and --exclude-standard options git ls-files will list files which are excluded by the .gitignore file or any other Git exclusions.

The xargs command passes each listed file to git rm --cached which removes it from the index.

I learnt this from an answer by thSoft on Stack Overflow.

Check and Commit

Whichever approach you find most suitable you can use git status to list all the files that have been removed from the index prior to committing. Files which have been removed from the index will be marked as deleted. Once you’re happy, commit your changes.

You’re all done. Be aware that when other developers pull this change their working tree will be modified.