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.
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:
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,
**/*.jsonwill 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.
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
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
git add -f debug.log
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