WordPress Migration Skill
This skill provides expertise for working with the wp-migrate.sh WordPress migration tool.
Project Overview
wp-migrate.sh is a comprehensive WordPress migration tool that operates in two modes:
- Push Mode: Migrates WordPress sites between servers via SSH (source → destination)
- Archive Mode: Imports WordPress backup archives (Duplicator, Jetpack Backup, Solid Backups) on destination server
Current Version: Check the latest release
git describe --tags --abbrev=0 # Get current version from git
Latest Release: See GitHub Releases
Repository: BWBama85/wp-migrate.sh
Main Branch: main
Core Capabilities
Migration Modes
Push Mode
- Transfers wp-content and database from source to destination via SSH
- Enables maintenance mode on both servers during migration
- Creates timestamped backups before overwriting
- Performs URL search-replace to align destination domain
- Excludes object-cache.php to preserve destination caching infrastructure
- Supports StellarSites managed hosting compatibility (--stellarsites flag)
Archive Mode
- Auto-detects archive format (Duplicator, Jetpack Backup, Solid Backups)
- Extracts archives to temporary directory
- Validates disk space (requires 3x archive size)
- Creates backups of destination database and wp-content before import
- Automatically aligns table prefixes if different from wp-config.php
- Performs URL search-replace to align with destination URLs
- Provides rollback instructions with exact commands
Key Features
- Migration preview with confirmation: Pre-migration summary with detailed stats and confirmation prompt (v2.6.0)
- Rollback command: Automatic restoration from backups with --rollback flag (v2.6.0)
- Progress indicators: Real-time progress bars for long-running operations when pv is installed (v2.6.0)
- Dry-run mode: Preview all operations without making changes (--dry-run)
- Verbose logging: Show detailed diagnostic information (--verbose)
- Trace mode: Show every command before execution (--trace)
- Plugin preservation: Preserve destination plugins/themes not in source (--preserve-dest-plugins)
- StellarSites mode: Managed hosting compatibility with mu-plugins exclusion (--stellarsites)
- Skip search-replace: Fast migrations that only update home/siteurl options (--no-search-replace)
- Automation support: Skip confirmation prompts with --yes flag for CI/CD (v2.6.0)
- Quiet mode: Suppress progress indicators for non-interactive scripts with --quiet (v2.6.0)
Common Tasks
Running Migrations
Push Mode:
./wp-migrate.sh --dest-host user@dest.example.com --dest-root /var/www/site
Archive Mode:
./wp-migrate.sh --archive /path/to/backup.zip
./wp-migrate.sh --archive /path/to/backup.tar.gz --archive-type jetpack
Dry Run:
./wp-migrate.sh --dest-host user@dest --dest-root /var/www/site --dry-run --verbose
Rollback (v2.6.0):
./wp-migrate.sh --rollback # Auto-detects latest backups
./wp-migrate.sh --rollback --rollback-backup /path/to/specific/backup # Specific backup
./wp-migrate.sh --rollback --yes # Skip confirmation for automation
Automation-Friendly (v2.6.0):
./wp-migrate.sh --archive /path/to/backup.zip --yes --quiet # CI/CD: skip prompts, no progress bars
Testing
Run all tests:
make test
Run specific test:
./test-wp-migrate.sh
ShellCheck validation:
shellcheck wp-migrate.sh
Development Workflow
Code Structure (v2+)
The project uses a modular source structure:
src/
├── header.sh # Shebang, defaults, variable declarations
├── lib/
│ ├── core.sh # Core utilities (log, err, validate_url)
│ ├── functions.sh # All other functions
│ └── adapters/ # Archive format adapters
│ ├── README.md
│ ├── duplicator.sh
│ ├── jetpack.sh
│ └── solidbackups.sh
└── main.sh # Argument parsing and main execution
IMPORTANT: Modifications should be made in src/ files, NOT in wp-migrate.sh directly.
Build Process
After modifying source files:
make build
This will:
- Run shellcheck on concatenated source
- Concatenate src/ files into dist/wp-migrate.sh
- Copy to ./wp-migrate.sh (repo root)
- Generate SHA256 checksum
Pre-commit Hook
A pre-commit hook prevents committing source changes without rebuilding:
ln -s ../../.githooks/pre-commit .git/hooks/pre-commit
Git Workflow
- Branching: Create from main using descriptive names:
feature/<slug>for enhancementsfix/<slug>for bug fixesdocs/<slug>for documentationchore/<slug>for maintenance
- Commits: Use .gitmessage template format:
``` type: short imperative summary
Longer explanation if needed ```
Types: feat, fix, docs, chore, refactor, test
- Changelog: Update CHANGELOG.md under [Unreleased] section with every feature or fix
- Pull Requests:
- Use .github/pull_request_template.md checklist
- Include comprehensive summary based on ALL commits (not just latest)
- Include test plan with verification steps
- Reference related issues
- Merging: Keep main release-ready with
git merge --no-ffor squash after review
- Releases: Tag with semantic versioning (e.g.,
git tag v2.7.0)
Creating Pull Requests
When creating PRs, ensure:
- Review ALL commits in the branch (use
git log main..HEADandgit diff main...HEAD) - Summary covers complete scope of changes
- Test plan verifies all functionality
- CHANGELOG.md is updated
- ShellCheck passes
- Tests pass (make test)
Common Files to Check
- [wp-migrate.sh](wp-migrate.sh) - Main script (built artifact, don't edit directly)
- [src/](src/) - Modular source files (edit these)
- [src/lib/adapters/](src/lib/adapters/) - Archive format adapters
- [CHANGELOG.md](CHANGELOG.md) - Version history
- [README.md](README.md) - User documentation
- [Makefile](Makefile) - Build and test targets
- [test-wp-migrate.sh](test-wp-migrate.sh) - Test script
Troubleshooting Guide
Common Issues
Permission Errors on Managed Hosts (StellarSites)
- Symptom: "Permission denied" when syncing wp-content
- Solution: Use
--stellarsitesflag to exclude protected mu-plugins - Details: Managed hosts protect certain mu-plugins directories (e.g.,
stellarsites-cloud)
Database Import Fails
- Check table prefix alignment (script auto-detects and updates wp-config.php)
- Verify sufficient disk space (3x archive size for archive mode)
- Check MySQL max_allowed_packet size for large imports
URL Search-Replace Issues
- Use
--verboseto see detected URLs - Override with
--dest-home-urlor--dest-site-urlif detection fails - Use
--no-search-replacefor faster migrations that only need home/siteurl updated
Archive Detection Fails
- Use explicit
--archive-typeto specify format (duplicator, jetpack, solidbackups) - Verify archive structure matches adapter expectations (see src/lib/adapters/)
- Check detailed validation errors with --verbose (v2.6.0+)
Non-Interactive Context Failures (v2.6.0)
- Symptom: Script exits with "This script requires a TTY for confirmation prompts"
- Solution: Add
--yesflag when running in CI/CD, cron, or pipeline contexts - Details: Migration preview and rollback require confirmation by default; use --yes to bypass
Rollback Issues (v2.6.0)
- Auto-detection looks for latest timestamped backups in db-backups/ and wp-content.backup-*
- If backups aren't found, use
--rollback-backup /path/to/backupto specify explicitly - Rollback only works for archive mode migrations (restores from local backups)
SSH Connection Issues
- Add custom SSH options with
--ssh-opt(can be repeated) - Examples: `--ssh-opt 'Port