RMD Migrate from Localdev self-updates
WordPress plugin that prepares a local development site for upload: database dump with serialization-safe search and replace plus a copy of all files, ready for SFTP and phpMyAdmin.
by Philipp Reichelt, reichelt media.design · github.com/reicheltmediadesign/wordpress-rmd-migrate-from-localdev · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/reicheltmediadesign/wordpress-rmd-migrate-from-localdev/archive/refs/heads/main.zipShips its own WordPress updater (Plugin Update Checker), so new versions show up under Dashboard → Updates.
WordPress plugin that prepares a local development site for upload to a staging or production server. It writes a copy of all files and a database dump in which every address and path of the local site is replaced by that of the target, safe for serialized data. Uploading stays with you: files via SFTP, database via phpMyAdmin. Built by reichelt media.design.
Features
- Serialization-safe search and replace. Serialized PHP values (widgets, theme and plugin settings) are parsed, rewritten and re-serialized with correct lengths. Objects are never instantiated, so classes that are not loaded survive unchanged. Serialized data nested inside strings is handled as well.
- Every spelling of the local address:
http://andhttps://, protocol-relative (//localhost/site), without scheme (localhost/site), JSON-escaped (http:\/\/localhost\/site), URL-encoded, and links relative to a local subfolder (href="/site/…",url(/site/…)). - Local file paths (
C:\xampp\htdocs\site,C:/xampp/…, JSON-escaped) are replaced by the server path of the target. - The local database is never changed. Replacements happen while writing the dump.
- Profiles for several targets, e.g. "Development" and "Production", each with its own address, server path, table prefix and options.
- Complete site copy with sensible exclusions (
.git,node_modules, caches, backups, logs, Markdown files in the WordPress folder) and your own rules in.gitignoresyntax. - Linked plugin repositories (junctions/symlinks in
wp-content/plugins): if the repository contains a built release zip (dist/<folder>.zip), that zip is used; otherwise its.distignoreapplies, so no development files end up on the server. - Ready for the target:
.htaccesswith the rightRewriteBase, awp-config.phptemplate with placeholders for the database credentials, new security keys, debugging off andWP_ENVIRONMENT_TYPEset. - Optional table prefix change, including the keys WordPress stores with the prefix (
<prefix>user_roles,<prefix>capabilities, …). - Leaner dump: transients, this plugin's own data and optionally revisions and spam are left out; tables like Yoast's indexables are exported empty because the plugin rebuilds them.
- Compatible dump for phpMyAdmin: gzip-compressed, batched inserts, binary data as hex, collations of MySQL 8 and new MariaDB versions replaced for older servers (optional).
- Report (
MIGRATION.txt) with next steps, rows and changed values per table, and every value that still refers to the local site. - Runs in short steps with a progress bar, so PHP time limits do not matter. An interrupted export can be continued.
- Only on local sites: exports are refused unless the site runs on
localhost,127.0.0.1, a*.local/*.test/*.localhosthost or withWP_ENVIRONMENT_TYPEset tolocal.
Requirements
WordPress 6.8 or newer, PHP 8.1 or newer, a single site (no multisite). The local site must be able to write to the export folder.
Installation
- Download
rmd-migrate-from-localdev.zipfrom the latest release. Do not use the “Source code” downloads, they lack the update library. - In your local WordPress go to Plugins → Add New → Upload Plugin, choose the zip and activate it.
- Open Tools → Migrate from localdev.
The plugin is not copied into its own exports and is removed from the list of active plugins in the dump, so it never runs on the target.
Usage
-
Add a profile per target with its site address, e.g.
https://example.com, and ideally the server path of the WordPress folder on the target. -
Click Export. The progress bar shows the current table or file count.
-
Open the export folder shown at the end. It contains:
Entry Use files/The complete site. Upload its contents into the web root of the target (SFTP). database.sql.gzImport in phpMyAdmin (Import tab) into the database of the target. Existing tables with the same names are replaced. wp-config-template.phpOnly for a new installation: enter the database credentials of the target and upload it as wp-config.php.MIGRATION.txtNext steps, statistics and remaining references to the local site. -
On the target: log in with your local users, save Settings → Permalinks once and clear caches.
wp-config.php is never part of files/, so an existing configuration on the target is not overwritten.
Settings
Profile
| Setting | Default | Description |
|---|---|---|
| Name | – | E.g. "Development" or "Production". |
| Site address | – | Address of the site on the target. Replaces every spelling of the local address. |
| Server path | empty | Absolute path of the WordPress folder on the target server. Local file paths stored by plugins are replaced with it. Empty = paths stay and are listed in the report. |
| Table prefix | local prefix | Prefix of the tables in the dump. Must match $table_prefix on the target. |
| Environment type | Production | WP_ENVIRONMENT_TYPE in the wp-config.php template. |
| Copy files | on | Copy the complete WordPress folder. Off = database only. |
| Leave out | see below | Exclusion rules, one per line. |
| Tables without data | actionscheduler_logs, yoast_indexable, yoast_indexable_hierarchy, yoast_seo_links |
Tables (without prefix) that are created empty. |
| GUIDs | on | Also replace the local address in post GUIDs. |
| Relative links | on | Adjust links like /subfolder/wp-content/… when the local site lives in a subfolder. |
| Revisions | off | Leave out post revisions. |
| Spam | on | Leave out spam and trashed comments. |
| Compatibility | on | Replace utf8mb4_0900_* and utf8mb4_uca1400_* collations with utf8mb4_unicode_520_ci. |
| Compression | on | Save the dump as .sql.gz. |
Exclusion rules
The syntax follows .gitignore: name matches a file or folder at any depth, /name only directly in the WordPress folder, a trailing / only folders, * and ? stay within a path segment, ** spans segments. Matching is case-insensitive. Defaults:
.git/
.github/
.svn/
node_modules/
.idea/
.vscode/
/*.md
/wp-content/cache/
/wp-content/upgrade/
/wp-content/upgrade-temp-backup/
/wp-content/ai1wm-backups/
/wp-content/updraft/
/wp-content/uploads/backwpup-*/
*.log
.DS_Store
Thumbs.db
desktop.ini
Always left out: wp-config.php, .htaccess (a version for the target is written instead), the export folder and this plugin.
Export folder
Under Settings on the plugin page. Default is wp-content/rmd-migrate-exports (protected by a .htaccess deny rule); a folder outside the web root is better, e.g. C:\Users\<name>\Exports. Exports can be deleted on the plugin page.
Developer hooks
- Filter
rmd_mfl_is_local_environment( bool $is_local, string $host )– override the detection of local sites. - REST (administrators on local sites only):
GET|POST|DELETE /wp-json/rmd-migrate-from-localdev/v1/export,POST …/export/step.
Privacy
The plugin makes no external requests, except for checking GitHub for plugin updates from the WordPress admin. Exports contain the complete database including user accounts and password hashes; keep them private and delete them when they are no longer needed.
License
GPL-2.0-or-later. Uses plugin-update-checker (MIT).