Secrets

Secrets and What Never Goes into Version Control

A .env file holding defaults belongs in Git 1,932 . One holding a live database password is a breach waiting for the day the repository is made public, forked, or cloned onto a laptop that gets stolen. Commit nothing you would not paste into a public issue; let the platform supply the rest.

.gitignore — deny real secrets, allow the templatesJavaScript
.env
.env.*
!.env.example
*.pem

The ! line matters: ignoring .env.* and then re-allowing .env.example gives contributors a file to copy with no chance of a real value beside it. Generate that template from the live file, writing only the keys.

tools/make-example.mjs — the keys, never the valuesJavaScript
import { readFileSync, writeFileSync } from 'node:fs';
import { parseEnv } from 'node:util';
const keys = Object.keys(parseEnv(readFileSync('.env', 'utf8')));
writeFileSync('.env.example', keys.map((k) => `${k}=`).join('\n') + '\n');
console.log(`wrote .env.example with ${keys.length} keys`);

It prints wrote .env.example with 4 keys for the file above. Deleting a committed secret in a later commit fixes nothing: the blob stays in the history, in every clone, and in any fork. Rotate the credential first — assume it is burned the moment it reaches a remote — then rewrite history with git-filter-repo 13,338 (github.com/newren/git-filter-repo (https://github.com/newren/git-filter-repo 13,338 )) and force-push.

Open-source tools for keeping secrets out of a repository, versions of 17 September 2026
Tool License What it does Where it runs
gitleaks 8.30.1 29,524 MIT Entropy scan of diffs pre-commit hook, CI
TruffleHog 3.97.5 28,147 AGPL-3.0 Verifies found keys CI sweeps
SOPS 3.13.3 23,231 MPL-2.0 Encrypts file values dev machines, CD
dotenvx 2.28.0 5,814 BSD-3-Clause Encrypts .env local, production

gitleaks protect --staged in a pre-commit hook takes well under a second on a normal diff, and gitleaks detect in CI catches what a machine that skipped the hook let through. SOPS and dotenvx go further: commit the file encrypted, and give the servers only the decryption key.