A well-defined Git branching strategy is the difference between a WordPress project where multiple developers can ship features independently and one where every merge causes conflicts and deployments feel risky. The two most widely adopted strategies are Git Flow, which uses long-lived develop and main branches plus short-lived feature/, release/, and hotfix/ branches, and the simpler trunk-based development approach where all work lands on main through short-lived feature branches. For most WordPress agency and product teams the Git Flow variant strikes the right balance: main always reflects production, develop is the integration branch where completed features accumulate before a release, feature/* branches are created from develop for each new feature or bug fix, and hotfix/* branches are cut directly from main for urgent production fixes. The hotfix is merged back into both main and develop to keep the branches in sync. Branch naming conventions matter — feature/add-custom-checkout-field, hotfix/fix-woocommerce-tax-rounding, and release/2.4.0 communicate intent immediately. Protecting the main branch on GitHub or GitLab to require pull request reviews before merging prevents accidental direct pushes to production. Combining branch protection with the Git hooks guide for pre-commit checks creates a quality gate at every step. The rebase and squash guide explains how to keep the commit history on develop clean before a release merge.
Problem: Multiple developers work on the same WordPress repository and direct commits to main cause deployment conflicts, accidental feature leaks, and no clear path for emergency hotfixes.
Solution: Adopt the Git Flow branching model with protected branches and a consistent naming convention:
# Initial repository setup
git checkout -b develop main
git push -u origin develop
# Start a new feature
git checkout develop
git pull origin develop
git checkout -b feature/add-shipping-calculator
# Work, commit, push
git add .
git commit -m "Add shipping calculator to cart page"
git push -u origin feature/add-shipping-calculator
# Open a pull request into develop (via GitHub/GitLab UI)
# After review and merge, clean up the feature branch
git checkout develop
git pull origin develop
git branch -d feature/add-shipping-calculator
git push origin --delete feature/add-shipping-calculator
# Create a release branch from develop
git checkout -b release/1.5.0 develop
# Bump version numbers, update changelog, final QA
git commit -am "Bump version to 1.5.0"
git checkout main
git merge --no-ff release/1.5.0 -m "Release 1.5.0"
git tag -a v1.5.0 -m "Version 1.5.0"
git push origin main --tags
git checkout develop
git merge --no-ff release/1.5.0
git push origin develop
git branch -d release/1.5.0
# Emergency hotfix on production
git checkout -b hotfix/fix-payment-redirect main
git commit -am "Fix payment redirect loop on checkout"
git checkout main
git merge --no-ff hotfix/fix-payment-redirect -m "Hotfix: payment redirect"
git tag -a v1.5.1 -m "Hotfix 1.5.1"
git push origin main --tags
git checkout develop
git merge --no-ff hotfix/fix-payment-redirect
git push origin develop
git branch -d hotfix/fix-payment-redirect
NOTE: Use --no-ff (no fast-forward) on all merges into main and develop to preserve a merge commit that makes the branch history legible — without it, fast-forward merges flatten feature history and make it harder to revert an entire feature. On GitHub, set the default merge strategy for pull requests to “Create a merge commit” for develop and “Squash and merge” for feature branches to get the best of both worlds: a single commit per feature on develop and a merge commit when releasing to main.