Technote

Development workflow Practical

A .gitignore for WordPress on GitHub

The line between what belongs in a WordPress repository and what must never enter it is sharp. The moment wp-config.php lands in a repo, your database password and auth salts ship with it.

Putting WordPress under version control by adding everything is how the accident starts. Core, uploads and configuration all live in one tree, so the first job is to draw the commit boundary. This is the rule set we actually use when moving client sites to Git.

The boundary, in one picture

One question decides everything: if this file were lost, could code recreate it? If yes (core, vendors, caches) — ignore it. If no (the theme and plugins you wrote) — commit it. The single exception is secrets: irreplaceable, and still never committed.

Only the code you wrote stays in the repository

Why wp-config.php comes first

It holds the database password and all eight auth salts in plain text. The moment the repository goes public — or a private repo leaks a single credential — everything needed to forge sessions for the whole site ships with it. We have inherited sites where a plaintext DB password sat committed in version control for years. Keep only wp-config.sample.php in the repo; real values are created on the server at deploy time.

A committed secret is not erased by a delete commit. It stays in history, already copied into every clone. The only real response is to revoke and reissue the values themselves.

A working .gitignore

# Secrets — never
wordpress/wp-config.php
.env

# Core — reproducible from a version number
wordpress/wp-admin/
wordpress/wp-includes/
wordpress/wp-*.php
wordpress/index.php

# User artefacts and runtime
wordpress/wp-content/uploads/
wordpress/wp-content/upgrade/
wordpress/wp-content/cache/

# Build and tooling
node_modules/
*.sql
*.log

Pinning core without committing it

Record the version number instead of the files. A deploy script running wp core download --version=X.Y reproduces the same tree on any server. Committing core bloats the repository and turns every core update into a thousand-file diff that buries the review of your own code.

Core is managed as a version number, not as files

If it is already committed

  • Secrets — rotate the DB password and reissue salts now (api.wordpress.org/secret-key/1.1/salt/). Cleaning history is the second problem.
  • Large files — remove them from history with git filter-repo; plan for a full re-clone if you collaborate.
  • From today — add the .gitignore, then git rm -r --cached to stop tracking without touching the server.

Drawing this boundary is half of a deployment workflow. The other half — shipping exactly what staging verified — is what our work process documents, and the full service is described in the optimization program.

More on this topic

All technotes

Development workflow Practical

Turning taste arguments into rule checks

"It feels a bit cramped" can be neither argued with nor fixed. Spacing off the scale, colour off the palette, contrast below threshold, missing states — four rules…

Designers 9 min read

Development workflow Practical

Do not swap everything at once

A full swap makes every problem appear at the same moment — which means none of them can be attributed. So you switch one template at a time.

Designers 6 min read

Development workflow Practical

Adding an SCSS build, and whether to commit the output

WordPress themes are expected to deploy without a build step, which leads to the opposite conclusion from ordinary application code — and to its own costs.

Developers 7 min read

₩270,000 · Join the program