• Docs
  • Talk to an expert
Blog
Blog
BlogProductCase studiesNewsInsights
Blog

What is a .gitignore file? How it works, with examples

GitGitOpsconfigurationdeveloper workflowopen source
03 November 2026
Share
This post is also available in German and in French.

TL;DR

  • A .gitignore file is a plain text list of files and folders that Git should leave out of your repository.
  • Each line is a pattern, such as .env or node_modules/, that matches one or more paths.
  • Typical entries are secrets, installed dependencies, build output, logs, and editor or operating system clutter.
  • It only affects files Git is not already tracking. A file committed before you ignored it needs git rm --cached to stop being tracked.
  • Your .env file belongs in .gitignore. Commit a .env.example with placeholder values instead.
  • .gitignore only controls what Git commits. AI coding agents working on your machine can still read ignored files, including .env, so use your tool's own ignore or permission settings too.
  • On Upsun Cloud, real secrets go into project or environment-level variables, so they never need to be in the repository at all.


 A .gitignore file is a plain text file that tells Git which files and folders to leave out of your repository. You list what you want ignored, one pattern per line, and Git stops offering those files when you stage and commit your work.

If you have ever opened a project and found a file called .gitignore sitting next to the code, this guide explains what it is doing there. It covers how the file works, what usually goes in it, the pattern rules, and how to fix the most common problem: a file that Git keeps tracking even after you ignored it.

How a .gitignore file works

Key takeaway: Git reads .gitignore before it decides which new files to show you, and skips anything that matches a pattern in it.

Git is the tool most developers use to track changes to their code. It watches a project folder and notices every new or changed file. Without instructions, it would offer to save everything, including passwords, downloaded libraries, and temporary files your computer creates on its own.

A .gitignore file is that set of instructions. It usually sits in the top folder of a project, and each line describes files to skip. When you run git status to see what has changed, or git add to prepare files for a commit, Git checks each new file against those lines. Matching files stay out of sight.

The file only affects files Git is not tracking yet. Git's documentation describes its purpose as keeping untracked files untracked, so a file that was already committed stays tracked until you untrack it (see common mistakes below). A few other details shape how it behaves:

  • The .gitignore file is committed like any other file, so everyone who clones the project gets the same rules.
  • A .gitignore in a subfolder applies to that folder and everything inside it.
  • Rules that only matter on your machine, such as files your own editor creates, can go in a global ignore file or in .git/info/exclude, which is never shared.

What to put in a .gitignore file

Key takeaway: ignore anything that is secret, anything that can be rebuilt, and anything specific to one person's machine.

Most entries fall into five groups:

What to ignoreWhyExample entries
Secrets and local settingsPasswords and API keys in a repository can be read by anyone with access to it.env, .env.local, *.pem
Installed dependenciesDownloaded libraries are large and can be reinstalled from a lock filenode_modules/, vendor/, .venv/
Build outputGenerated files are recreated every time the project is builtdist/, build/, *.pyc
Logs and temporary filesThey change constantly and are only useful on the machine that made them*.log, tmp/
Editor and system clutterFiles your editor or operating system creates on its own.DS_Store, .idea/, .vscode/

Here is a short .gitignore for a typical web project. Lines that start with # are comments, which Git skips.

# Secrets and local settings
.env
.env.local

# Dependencies
node_modules/
vendor/

# Build output
dist/

# Logs
*.log

# Editor and operating system files
.DS_Store
.idea/
.vscode/

You rarely need to write one from scratch. GitHub maintains a public collection of .gitignore templates for most languages and frameworks, and many project starters create one for you.

Should .env be in .gitignore?

Key takeaway: yes. Ignore your .env file and commit a .env.example with placeholder values so teammates know which settings the project needs.

A .env file holds settings your app reads when it starts, often including database passwords and API keys. (Our guide What is .env? covers it in full.) Because those values are secret, the .env file is usually the first line in any .gitignore.

A new teammate who clones the project gets no .env file, so they cannot tell which settings the app expects. The common fix is a second file, .env.example, that lists the same names with dummy values. It is safe to commit because nothing in it is real. Each developer copies it to .env and fills in their own values.

# .env.example
DATABASE_URL=your-database-url-here
PAYMENT_API_KEY=your-key-here

Ignoring .env protects you from now on. It does not undo the past: if a secret was ever committed, it stays in the project's history. The safe response is to replace that password or key with a new one, then remove the file from tracking.

Does .gitignore stop AI coding agents from reading .env?

Key takeaway: no. .gitignore keeps files out of Git, not out of reach. AI coding agents on your machine can read anything your user account can read.

An AI coding agent such as Cursor, Claude Code, or Codex works inside your project folder, with the same access to files that you have. .gitignore tells Git what to leave out of commits. It doesn't hide files from anything else running on your computer, so an agent can open your .env file, print its values, or paste them into a chat.

Most tools give you a separate way to keep agents away from sensitive files:

  • Cursor skips files listed in .gitignore by default, along with .env files, and you can add more patterns in a .cursorignore file. Cursor's documentation notes that the agent's terminal and MCP tools can still read ignored files.
  • Claude Code lets you add deny rules in its settings file, such as a rule that blocks reading .env.

Treat these as a safety net, not a guarantee. The safest setup is to keep only development or test keys in your local .env file, and keep production secrets out of your machine entirely.

.gitignore syntax cheat sheet

Key takeaway: a handful of symbols covers almost every case. A trailing slash means folders only, a star matches any characters, and an exclamation mark makes an exception.

PatternWhat it ignoresExample match
.envAny file or folder named .env, in any folder.env, api/.env
/.envOnly the .env in the same folder as the .gitignore.env, but not api/.env
logs/Folders named logs, and everything inside themlogs/today.log
*.logAny file ending in .logerror.log, app/debug.log
**/tempA file or folder named temp at any depthtemp, src/old/temp
docs/**/*.pdfPDF files anywhere under docsdocs/guides/setup.pdf
!keep.logAn exception: do not ignore this file, even if an earlier line didkeep.log stays tracked
# noteA comment, which Git skipsNothing


Two rules trip people up most often. First, when two lines disagree, the later one wins, so put exceptions after the rule they override. Second, you cannot make an exception for a file inside a folder you have ignored entirely, because Git never looks inside that folder. Ignore the folder's contents (logs/*) instead of the folder itself if you need exceptions inside it.

Common .gitignore mistakes and how to fix them

Key takeaway: if Git still tracks a file you ignored, it was committed first. Untrack it with git rm --cached and commit the change.

The file was already committed

This is usually why a .gitignore seems to be broken. Git only ignores files it is not already tracking. To stop tracking a file but keep your local copy, run:

git rm --cached .env
git commit -m "Stop tracking .env"

For a whole folder, add -r, as in git rm -r --cached node_modules. Your files stay on your computer. They disappear from the repository from the next commit onward, though they remain in its history.

The pattern does not match what you think

To see which line, in which file, is ignoring a path, run git check-ignore -v followed by the path. If nothing prints, no rule matches it.

There is one catch: by default, the command skips files Git already tracks, so it prints nothing for them even when a rule matches. Add --no-index to check one of those:

git check-ignore -v --no-index .env

The file is in the wrong place or has the wrong name

The file must be called exactly .gitignore, with the leading dot and no extension. Notepad on Windows, for example, can save it as .gitignore.txt. Patterns are also read relative to the folder the .gitignore sits in.

Personal clutter in the shared file

Files only your setup creates, such as one editor's settings folder, are better kept in your global ignore file. That keeps the shared .gitignore focused on what matters to the whole project.

By language and framework

Key takeaway: every language leaves its own trail of installed packages and build files. Ignore those, and keep the files that describe what to install.

The secrets and editor clutter from earlier apply to every project. What else to ignore depends on the language, because each one installs packages and builds files in its own folders:

Language

Add to .gitignore

Keep in Git

PHPvendor/composer.json and composer.lock
Node.jsnode_modules/, plus build folders such as dist/ or .next/ for Next.jspackage.json and your lock file, such as package-lock.json
Python__pycache__/, *.pyc, and virtual environment folders such as .venv/pyproject.toml and your lock file, such as uv.lock
Ruby.bundle/ and vendor/bundle/, plus log/ and tmp/ in Rails appsGemfile and Gemfile.lock
Javatarget/ for Maven, or build/ and .gradle/ for Gradlepom.xml or build.gradle
.NETbin/ and obj/Project files such as .csproj

The pattern is the same in every row. Ignore what can be rebuilt, and commit the files that describe how to rebuild it, including the lock file. Our guide What is a lock file? explains why the lock file belongs in Git.

Many frameworks create a starter .gitignore for you when you start a new project, Laravel and Rails among them, so check what's already there before adding lines. For anything missing, GitHub's collection of .gitignore templates has a ready-made file for most languages and frameworks.

How Upsun Cloud handles secrets without committed files

Key takeaway: on Upsun Cloud, secrets live in project or environment-level variables, not in files, so your .env can stay ignored and your app still gets the values it needs.

Upsun Cloud builds and deploys your app from your Git repository, so an ignored .env file never reaches it.

The real passwords come from variables you set in Upsun Cloud itself, through the Console or the command line. Two levels matter here:

  • Project variables apply to every environment. They suit secrets that are the same everywhere, such as credentials for a shared service.
  • Environment-level variables apply to one environment, such as production. They suit values that differ, like using test payment keys in a preview environment and live ones in production.

A few options make this work in practice. Marking a variable as sensitive hides its value in the Console and in command line output, while your app can still read it. A production-only secret can be set so that other environments do not inherit it. And giving a variable the env: prefix exposes it to your app as an ordinary environment variable, so code that already reads its settings from the environment needs no changes.

For example, this command stores a production-only payment key that stays hidden and is not passed down to other environments:

upsun variable:create --level environment -e main --name env:PAYMENT_API_KEY --value your-key-here --sensitive true --inheritable false

Upsun's documentation also points out that values you set in the project's own configuration file are committed to Git, which makes them a poor fit for secrets. Keep those for settings that are safe to share. So .gitignore keeps secrets out of your code, and Upsun Cloud variables deliver them to the running app. See setting variables in the Upsun docs for every option.

Don't ignore the .environment file

Upsun Cloud does not read .env files at all. It does read a different file, .environment, from your app's root folder. This file runs as a script when your app's container starts, and it can set environment variables for the app. Projects set up with upsun project:init may already have one, for example to pass database details to the names a framework expects.

Despite the similar name, .environment must be committed so Upsun Cloud can use it. Check that no pattern in your .gitignore, such as .env*, catches it by accident. Because it is committed, keep secrets out of it too: it should point to variables, not contain passwords.

Upsun Cloud builds every environment from your Git repository and keeps secrets in variables, so a clean .gitignore is all your repository needs. You can deploy on Upsun Cloud free for 15 days, with no card needed, or see how Git-driven automation works.

Frequently asked questions (FAQ)

What is a .gitignore file used for?

It tells Git which files and folders to leave out of a repository. Teams use it to keep secrets, installed libraries, build output, and machine-specific files out of shared code.

Where should the .gitignore file go?

Usually in the top folder of the project, next to the hidden .git folder. You can add more .gitignore files in subfolders, and each one applies to its own folder and everything below it.

Should I commit the .gitignore file?

Yes. Committing it means everyone working on the project ignores the same files.

Why is my .gitignore not working?

The file was most likely committed before you added the rule. Run git rm --cached on it and commit. If that is not the cause, run git check-ignore -v with the file path to see which rule, if any, applies.

Does .gitignore delete files?

No. Ignored files stay on your computer. Git simply stops offering them for commits.

Does .gitignore stop AI coding agents from reading my .env file?

No. It only controls what Git commits. Use your coding tool's ignore or permission settings, such as a .cursorignore file in Cursor or deny rules in Claude Code, and keep production secrets out of your local .env.

Does .gitignore remove secrets that were already committed?

No. Anything committed stays in the project's history. Replace the exposed password or key with a new one, then untrack the file.

What is the difference between .gitignore and .git/info/exclude?

Both use the same pattern rules. The .gitignore file is shared with everyone through the repository, while .git/info/exclude stays on your machine only.

Stay updated

Subscribe to our monthly newsletter for the latest updates and news.

Deploy possibility.
Try Upsun for free.

Build with DispatchDeploy on Cloud