Files Git Should Never See
Topic 20

Files Git Should Never See

Housekeeping

Run git status on a real project and it will offer you things you have no interest in committing: a file your editor created, a folder your tools generated, a note containing a password.

The fix is a file called .gitignore: a plain text list of what Git should pretend it cannot see. It sits at the top of the repository, it is committed like any other file, and it is one of the first things you should write in a new project.

The four categories

Secrets — passwords, API keys, tokens, anything in a .env file. This is the expensive category: a committed secret is a security problem rather than a tidiness problem, and the next topic covers what to do when it happens.

Generated output — build folders, compiled files, anything your tools produce from your source. It can be recreated at any time, so storing it just makes every diff unreadable.

Dependencies — libraries installed by a package manager, of which node_modules/ is the famous example. Enormous, reinstallable from a single list, and the usual reason a beginner's first repository is several hundred megabytes.

Machine noise.DS_Store on macOS, Thumbs.db on Windows, your editor's settings folder. Individually harmless, collectively enough to make git status unreadable, which means you stop reading it.

Writing one

Create a file called .gitignore in the top folder of the project. One pattern per line:

Sandpiper's .gitignore
# machine noise
.DS_Store
Thumbs.db

# local notes, not for the club
notes/private/

# anything with credentials in it
.env
*.key

A plain name matches that file. A name ending in a slash matches a whole folder. An asterisk stands for "anything", so *.key matches every file with that extension. A line starting with # is a comment, and comments are worth writing — six months later "why is this ignored" is a real question.

What ignoring actually does

Ignored files stop appearing in git status and are never picked up by git add .. They stay on your disk, completely untouched; Git simply stops mentioning them.

Before and after, on the same folder
git status        # four untracked files, three of them noise
git add .gitignore
git status        # one clean line

That second reading is the point. A status output you can take in at a glance is a status output you will actually read, and reading it is what stops the accidents in the rest of this chapter.

The same folder, with each entry's status and the rule responsible
sandpiper/
repository root
index.html
tracked — committed, watched for changes
.gitignore
tracked — the rules themselves are committed on purpose
.DS_Store
ignored
matched by: .DS_Store
notes/private/
ignored
matched by: notes/private/
sightings.js
untracked — not ignored, just not added yet

.gitignore is itself committed

This surprises people, who assume a file about what to hide should itself be hidden. The opposite: the rules belong in the repository so that everyone working on the project ignores the same things.

Commit the rules like anything else
git add .gitignore
git commit -m "Ignore local notes and system files"

The file contains rules, not secrets. Nobody learns anything dangerous from reading that you ignore .env — they learn it from reading .env itself, which is exactly what the rule prevents.

Where to get a good one

You do not have to invent these. GitHub offers a ready-made .gitignore for every common language and toolchain when you create a repository, and those templates are maintained by people who know which files a given toolchain leaves behind.

Start from the template for whatever you are building and add your own lines. For Sandpiper — plain HTML and CSS — the four lines above are genuinely enough.

The one thing it cannot do

An ignore rule applies to files Git is not already tracking. Add a rule for a file that has already been committed and nothing happens: Git keeps tracking what it already tracks.

That is the single most surprising behaviour in this chapter, and it is the whole of the next topic.

Common Confusions
  • "Ignoring a file deletes it." The file stays exactly where it is on your disk. Git stops watching it and stops mentioning it, and that is the entire effect.
  • ".gitignore should itself be secret." It is shared on purpose, so that everyone on the project ignores the same things. Its contents are rules, not credentials.
  • "Adding a file to .gitignore removes it from the repository." Not if it is already tracked. Ignore rules only apply to files Git has not been asked to record, which is the next topic.
  • "I can add ignore rules later, once the project is bigger." The expensive mistakes happen in the first week, before anyone is being careful. Four lines on day one is the cheapest insurance in this book.
Why It Matters
  • A committed secret is a real incident with a real cost, and a .gitignore written before the first commit is what prevents it.
  • Ignoring generated output keeps diffs readable. Nobody can review a change that includes ten thousand lines of build output, and in Chapter 8 somebody will be trying.
  • A short, clean git status is a status you actually read — which is the habit every accident in Chapter 4 was avoidable by.

Knowledge Check

What happens to a file on your disk when you add it to .gitignore?

  • Nothing at all, since it stays where it is and Git simply stops mentioning it
  • It is moved into a hidden folder so that it cannot be committed by accident
  • It is deleted, since Git assumes anything ignored is no longer needed
  • It is committed once more, then excluded from every commit after that

Why is .gitignore committed to the repository rather than kept private?

  • So that everyone working on the project ignores exactly the same files
  • Because Git refuses to read the file unless it has been committed first
  • Because an uncommitted .gitignore is deleted the next time you switch branches
  • Because the rules would otherwise be visible to anyone who clones the project

You add .env to .gitignore, but it was committed last week. What happens?

  • Nothing changes, since Git keeps tracking a file it already tracks
  • The file is removed from the repository at your next commit
  • The file is removed from every past commit in the history
  • Git reports an error because the rule conflicts with an existing tracked file

Which of these belongs in a .gitignore for almost any project?

  • Installed dependency folders, which are huge and reinstallable from one list
  • The main source files, since they change most often and create the largest diffs
  • The .gitignore file itself, so that its rules stay out of the history
  • The README, because its contents are meant for people rather than for Git

You got correct