ShieldThemes Web Development
+1 (415) 555-0142 Get a quote →
← Journal/WordPress

A Git-based deployment workflow for WordPress teams

Version control, Composer, staging and automated deploys for WordPress, so changes stop being made live over FTP and start being reviewed.

Leo Tanaka
Leo Tanaka
Head of DevOps · Aug 26, 2025 · 5 min read
A Git-based deployment workflow for WordPress teams

A surprising number of business-critical WordPress sites are still changed by logging into production and editing things directly: installing plugins from the dashboard, tweaking theme files in the editor, uploading fixes over FTP. It works until the day it does not, and then nobody knows what changed or how to undo it. Moving a WordPress team to a Git-based workflow is one of the highest-value changes we make for clients, and it is less disruptive than most people expect.

What belongs in Git and what does not

The first decision is scope. WordPress mixes code, configuration and content in ways that confuse people new to versioning it. Our rule of thumb:

  • In Git: the custom theme, custom plugins, a Composer file listing every third-party plugin and its version, server configuration, and deployment scripts.
  • Not in Git: WordPress core files and third-party plugins themselves (installed by Composer), uploads, the database, and any secrets.
  • Managed separately: environment-specific settings such as database credentials, API keys and debug flags, supplied through environment variables.

Structuring the project this way, often with a Bedrock-style layout, means the repository describes exactly what should be running, and every environment can be rebuilt from it.

Composer for plugins and core

Managing plugins through Composer is the step teams resist most and appreciate most once it is in place. Every plugin, including premium ones through private repositories or artifact storage, is declared with a version constraint. Updates happen in a branch, get tested, and are merged like any other change.

{
  "require": {
    "php": ">=8.2",
    "roots/wordpress": "6.8.*",
    "wpackagist-plugin/redirection": "^5.5",
    "wpackagist-plugin/wordfence": "^8.0"
  }
}

We disable plugin installation and file editing in production through configuration. That removes a whole class of problems: plugins installed on a whim, updates applied directly to production during business hours, and malware that uses the file editor to persist.

If production can be changed without a commit, your repository is a suggestion rather than a source of truth.

Environments and the path to production

Every client site we manage has at least three environments: local development, staging and production. Larger teams add a preview environment per pull request. The flow looks like this:

  1. A developer creates a branch, makes changes locally and opens a pull request.
  2. Continuous integration runs coding standards checks, static analysis, unit tests where they exist, and a build of front-end assets.
  3. A colleague reviews the change. For content-affecting changes, the pull request includes screenshots or a preview link.
  4. Merging to the main branch deploys automatically to staging, where the client or QA can check it against a recent copy of production data.
  5. A tagged release or manual approval promotes the same build to production.

The key detail is that production receives the exact artifact that was tested on staging. We build once, then deploy that build to each environment, rather than rebuilding on every server and hoping the results match.

Database and content: the hard part

Code flows up from development to production. Content flows the other way, because editors create it in production. Mixing the two is where most WordPress workflows break down. We handle it with a few conventions:

  • Staging and local environments are refreshed from a sanitized copy of production on a schedule, with personal data anonymized.
  • Configuration that lives in the database, such as plugin settings, is either moved into code where the plugin allows it or documented as a manual release step.
  • Schema or data changes that a release needs are written as migration scripts run through WP-CLI during deployment, never as manual edits.
  • Block theme templates edited in the site editor are exported back to theme files and committed, so the repository stays authoritative.

Secrets deserve a specific mention. Database passwords, API keys and license keys never live in the repository, not even in a private one. We store them in the hosting platform's secret manager or an encrypted store, inject them as environment variables at runtime, and rotate them when anyone with access leaves the team. A surprising number of WordPress repositories we inherit contain a committed wp-config.php with production credentials, which effectively turns every developer laptop into a production access point.

Deploys, rollbacks and results

We use atomic deployments: each release is built into a new directory, and a symlink switches traffic to it once everything is ready. There is no moment where half the files are new and half are old, and rolling back means pointing the symlink at the previous release, which takes seconds. After each deploy, automated smoke tests hit key pages, the checkout if there is one, and critical forms, and alert the team if anything fails.

For a publishing client with a team of six developers and editors in two time zones, moving to this workflow reduced production incidents caused by changes from roughly two a month to one in the following six months. Deploys went from a nervous weekly event to several a day. The less visible benefit was onboarding: a new developer went from zero to a working local environment in under an hour, instead of the two days it used to take.

The workflow is a standard part of our CI/CD pipelines work for WordPress clients, and it depends on reliable staging environments that mirror production closely. Sites on our monthly care plans get plugin updates delivered through the same process, tested on staging before they reach production.

Move your team off live edits

Tell us how your team currently ships changes and where your site is hosted. We will reply within 24 hours with a migration plan and a fixed-price quote to get your site into version control without disrupting your editors.

Leo Tanaka
WRITTEN BY
Leo Tanaka
Leo runs our hosting and infrastructure practice — CI/CD, cloud cost, observability and the on-call rotation behind every care plan.
All articles by Leo Tanaka →
Want this on your project?
Get a fixed-price quote from a senior lead within 24 hours.
Request a quote →

Keep reading

How we shipped a support agent that resolves 62% of tickets
AI · 5 min
How we shipped a support agent that resolves 62% of tickets
What to learn in the two weeks before a website redesign
Design · 5 min
What to learn in the two weeks before a website redesign
Migrating to Shopify Plus without losing a single ranking
Shopify · 5 min
Migrating to Shopify Plus without losing a single ranking