Quick Links

A .gitignore file is a text file placed in your git repository that tells git not to track certain files and folders that you don't want being uploaded to your master repository. It has a lot of uses, and you will almost always need to configure it if you're setting up a new repo.

What's The Point Of .gitignore?

In most projects, there's a difference between code/config, and generated files from that code or config. The latter is usually not useful, and can generally be ignored.

Usually, you only want the code and config to be tracked through git. This is because the generated files are ephemeral, and if you delete them, you can just regenerate them again. There's often no point to uploading them, as they will simply complicate things and cause unnecessary merge conflicts.

This is a broad definition, so lets look at an example. In Node JS projects, there is a folder called

        node_modules
    

 that contains all the external packages that your code needs to run. You can delete this directory and completely rebuild it by running

        npm install
    

, which uses the

        package.json
    

 configuration to search for packages.

So what's the point of having the

        node_modules
    

 folder in Git? There isn't one really, as it's more complicated, can cause issues, and can even drastically increase the size of the Git repo in many cases.

If you ignore the whole directory, all of your coworkers can still generate their own local copy from the

        package.json
    

 file. So, instead, only

        package.json
    

 should be tracked in Git. Most things that get added to .gitignore follow this pattern. Build artifacts, like a

        ./bin/
    

 folder, don't get committed since they're a direct result of the code itself.

Other things can also be added to .gitignore for convenience. MacOS generates system files called

        .DS_store
    

, which you can always ignore. Perhaps you store API keys in

        .env/
    

 that you don't want being tracked in source control, you can add those too. Caches, logs, and other output can usually be ignored.

Using .gitignore

You'll need to create a file called .gitignore, with no extensions, in the root of your project where your

        .git
    

 directory is located. You can do this from your file browser, or from the command line with any CLI text editor:

nano .gitignore

You can configure this in many ways, but the main tools you have are:

  • * wildcards, which match any text and can be used to match any directory, or any file regardless of extension.
  • !, which works as a kind of whitelist that negates a previously excluded file. The main catch with this is that it only whitelists the file if it was directly excluded, and will not work for files in directories that were completely excluded.
  • **, which matches anything recursively into directories. For example, **/*.json will match any JSON file regardless of where it is, and src/** will match every file in the folder recursively. This is useful when you want to whitelist and not ignore the whole directory.

For example, a Node JS gitignore might look like the following:

node_modules/

build/

npm-debug.log

.env

.env.test

.env.production

.DS_Store

.npm

.eslintcache

logs/

*.log

npm-debug.log*

Whitelisting files with ! can be very useful for many configurations. For example, in one of my projects I had a tool called steamcmd which downloads dependencies for game servers from Steam. This tool is packaged into a single portable executable, but it produces a whole lot of junk that I don't want being tracked in Git.

The solution was to ignore everything in the folder, but whitelist the executable. This will work for any portably executable that expands like this or produces otherwise unneeded junk in the directory.

Project/steamcmd/**

!Project/steamcmd/steamcmd.exe

gitignore also uses some other Unix globbing patterns for matching strings, such as a question mark for matching a single character, or [a-z] which will match character sets.

You can also write multiple .gitignore files which can match files relative to themselves. This isn't really too useful as you can just include the rules in the root file, which is easier to track, but it could help with code repetition in some cases. However, the workaround is to use character sets to match multiple directories. For example, matching uppercase and lowercase directories with a set:

# Build results

[Dd]ebug/

[Dd]ebugPublic/

[Rr]elease/

[Rr]eleases/

If you're having issues with your .gitignore configuration, you can debug it with the check-ignore Git command:

git check-ignore -v testfile.json

Global .gitignore

Git also has a global setting for .gitignore, but it shouldn't really be used in most cases. This is because the global .gitignore on your computer does not apply to your coworkers, and only to commits made with your instance of Git.

If you'd like to set it anyway, you can do so with the following command:

git config --global core.excludesfile ~/.globalignore

Force Committing Or Stashing Ignored Files

Force committing is generally a bad idea --- you should probably add a whitelist for this specific file, because once committed, updates to this file won't be tracked. But, if you want to manually commit something, you can run git add with the --force parameter:

git add -f debug.log

Similarly, git stash can also stash local changes to ignored files, which can actually be useful as it won't effect the remote repo:

git stash --all