Karpton Logo

Inverting Your Gitignore

Written by Toni Karppi on

The purpose of a gitignore file is to tell git about files or directories that you don’t want it to track. An example of such a directory is the node_modules directory, if you’re working with node.

Let’s assume that we’re working on a node app with the following file structure.

file tree

In this case we do not want node_modules in our git repository, since it can be generated using package.json and package-lock.jsn. We also do not want the .env file in our repository either, since it can contain secret variables, like API keys. Our standard .gitignore file would look like

node_modules/
.env

This all seems reasonable at first glance. However, the problem with this approach stems from the fact that you don’t always know what kind of files that will get added to your repository. There are gitignore generators available that try to create gitignore files that cover a wide variety of common files that should be ignored, but they can only cover so much.

An alternative approach that I’ve found to be useful is to by default ignore everything in the root of the git repository; then you pick the files/directories you want in your repository and unignore them. For the above example, we would get a gitignore file that looks like

/*

!src/
!.gitignore
!package-lock.json
!package.json

Now git knows exactly about the files we want to track, and it leaves everything else out. For this small example, the gitignore is more verbose than the standard one. This is only because we’re only ignoring the files we already have in the repository, and we’re not including files that could be added to the repository.

Now we could add any weird file, e.g. foo.txt to the root of our repository, and git would ignore it. If we wanted git to start tracking foo.txt, we would just add the line !foo.txt to the gitignore file. Note that we only have to specify uningnored files inside of the root of the directory. By unignoring the src directory, we automatically unignore the app.js file.

A potential pitfall with using this approach is that you forget to unignore a file in the root of the repository. The git status command will show that everything is up to date, even though you’re missing a file. I have not found this to be a serious problem, as if there are any important missing files, my CI pipeline will report an error. Also, I don’t often add or remove files in my repository root after its initial creation.

Give it a try and see if you find it useful. Thanks for reading.