Committing a .env file is one of the most common ways secrets leak. API keys and database passwords end up in a public repository, and automated scanners find them quickly. The prevention is simple; the cleanup after a mistake is not.
Why this matters
Version control keeps history. Deleting a secret in a later commit does not remove it from earlier ones, and if the repository was ever public, or the secret was pushed to a remote others can read, you must assume it is compromised. Automated bots scan public repositories for credential patterns, and leaked keys can be abused quickly. Hosting platforms and security tools also scan for known token formats and may notify you or revoke the token.
Step 1: Ignore .env before the first commit
Add these lines to .gitignore at the project root:
.env
.env.*
!.env.example
The first line ignores the file, the second ignores variants such as .env.local and .env.production, and the third re-includes the template. Create .gitignore before the first git add.
Note that .gitignore only affects files not yet tracked. If a .env is already committed, adding it to .gitignore does nothing for it.
Step 2: Check what git is tracking
git ls-files | grep -i env
git status
If .env appears in git ls-files, git is tracking it. Remove it from tracking, keeping the local file:
git rm --cached .env
git commit -m "Stop tracking .env"
This stops future changes being committed, but the file's old contents remain in history.
Step 3: Commit a template
Create .env.example with the keys and placeholder values, no real secrets:
DATABASE_URL=postgres://user:password@localhost:5432/app
API_KEY=replace-me
This documents what the app needs. Copy it with cp .env.example .env to start.
Step 4: Catch mistakes automatically
- Pre-commit hooks can block commits containing secret patterns.
- Secret scanning built into hosting platforms and CI can flag leaked tokens.
- Code review should treat any
.envin a diff as a red flag.
If a secret has already been committed
Act in this order:
- Rotate the secret immediately. Generate a new key or password and revoke the old one at the provider. This is the only step that actually protects you. Everything else is damage limitation.
- Remove it from history if you want to, using a history-rewriting tool such as
git filter-repoor BFG Repo-Cleaner, then force-push. Everyone with a clone must re-clone or reset, and old copies, forks and cached views may still hold the secret, so rotation remains essential. - Check logs at the provider for use of the leaked credential.
- Look for the same value elsewhere, such as other repositories and CI settings.
Where secrets should live instead
- Local development: an ignored
.envfile. - CI/CD: the platform's encrypted secrets store.
- Production: the hosting platform's environment variable settings, or a dedicated secrets manager.
- Containers: secrets mechanisms rather than baking values into images.
Handling the file itself
A .env file is plain text, readable by anyone with access to the machine. Do not email it, paste it into chat or upload it to a service that stores it. When you need to inspect or edit one, use a tool that works locally. Docento's Text & Markdown Editor opens .env files in your browser without uploading them. See what is a .env file for the basics.
Habits that help
- Use least-privilege keys with limited scope and expiry.
- Use different credentials for development and production.
- Keep
.env.examplecurrent so people do not improvise. - Review
.gitignorewhen starting any new project.
Takeaway
Ignore .env before your first commit, commit .env.example instead and use proper secret stores in CI and production. If a secret does reach the repository, rotate it first, because removing it from history is not enough.