Four years old and no answer? So here we go…-
Let's take the following network setup as example (I'm using WP-CLI's site list command):
$ wp site list
+---------+--------------------+---------------------+---------------------+
| blog_id | url | last_updated | registered |
+---------+--------------------+---------------------+---------------------+
| 1 | http://wp.tmp/ | 2016-08-04 08:39:35 | 2016-07-22 09:25:42 |
| 2 | http://foo.wp.tmp/ | 2016-07-22 09:28:16 | 2016-07-22 09:28:16 |
+---------+--------------------+---------------------+---------------------+
The network site list would look like this:

We want to use the site with ID 2
as the new root site with the URL http://wp.tmp/
. This is actually the same problem as described in the question just with some other values for the ID and the URLs.
The multisite relevant part of the wp-config.php
looks probably like this:
const MULTISITE = TRUE;
const DOMAIN_CURRENT_SITE = 'wp.tmp';
const PATH_CURRENT_SITE = '/';
const SITE_ID_CURRENT_SITE = 1;
const BLOG_ID_CURRENT_SITE = 1;
const SUBDOMAIN_INSTALL = TRUE;
Updating database site settings
WordPress uses the tables wp_*_option
and wp_blogs
to find the matching blog for a given request URL and to build proper permalinks for this blog. So we have to change the values in the following three tables (for this example):
- In
wp_options
the keys home
and siteurl
- In
wp_2_options
the keys home
and siteurl
(in your case this would be wp_15_options
)
- In
wp_blogs
the column domain
for both sites with ID 1
and 2
(respectively 15
)
I'm using Adminer for this, but any other DB management tool (PhpMyAdmin) does the job as well. (The screenshots shows the GUI in German language but I guess the idea is clear.)

In wp_options
(the options table for site ID 1
) I changed the values of both keys home
and siteurl
from http://wp.tmp
to http://foo.wp.tmp
. (The screenshot above shows the state before the update.)
I did exactly the same with the table wp_2_options
but here I changed the value from http://foo.wp.tmp
to http://wp.tmp
.
Next step is to update the table wp_blogs
:
(Again, the screenshot shows the table before I made any change.) Here you simply switch the values from both sites in the domain
column:
wp.tmp
becomes foo.wp.tmp
and
foo.wp.tmp
becomes wp.tmp
Now you have to update the wp-config.php
to deal correctly with the new settings data:
const MULTISITE = TRUE;
const DOMAIN_CURRENT_SITE = 'wp.tmp';
const PATH_CURRENT_SITE = '/';
const SITE_ID_CURRENT_SITE = 1;
const BLOG_ID_CURRENT_SITE = 2; // This is the new root site ID
const SUBDOMAIN_INSTALL = TRUE;
At this point you have again a working WordPress multisite but with a new root site:
$ wp site list
+---------+--------------------+---------------------+---------------------+
| blog_id | url | last_updated | registered |
+---------+--------------------+---------------------+---------------------+
| 1 | http://foo.wp.tmp/ | 2016-08-04 08:39:35 | 2016-07-22 09:25:42 |
| 2 | http://wp.tmp/ | 2016-07-22 09:28:16 | 2016-07-22 09:28:16 |
+---------+--------------------+---------------------+---------------------+

Remember: during this process, your site will be not available and requests will end up in some nasty errors so you might want to arrange a 503 Service Unavailable
response in front of your WordPress installation. This could be done using .htaccess
.
Updating database content
Now comes the tricky part. At the moment, all URLs in the content tables are still pointing to the resources of the old sites. But replacing them is not that easy: Replacing every http://foo.wp.tmp
with http://wp.tmp
in the first step and every http://wp.tmp
with http://foo.wp.tmp
in the next step will end up in having all former URLs pointing to site ID 1 (http://foo.wp.tmp
).
The best way would be to insert an intermediate step:
- Search for
http://foo.wp.tmp
and replace it with a preferably unique slug: http://3a4b522a.wp.tmp
- Search for
http://wp.tmp
and replace it with http://foo.wp.tmp
- Search for
http://3a4b522a.wp.tmp
and replace it with http://wp.tmp
All these search and replace commands should ignore the three tables (*_options
*_blogs
) we updated before, otherwise they would break the configuration. You might also have a manual look for URLs in wp_*_options
table outside of the home
and siteurl
keys.
I would suggest to use WP-CLI's search-replace command for this as it can deal with serialized data and has no limitations that HTTP might have.
BLOG_ID_CURRENT_SITE
, and I thinkSITE_ID_CURRENT_SITE
probably needs to stay 1 (to match thewp_site
table). See the code inwp-includes/ms-settings.php
that uses these to setup$current_site->blog_id
- obviously you needDOMAIN_CURRENT_SITE
,PATH_CURRENT_SITE
set etc. Whether getting this right will do the trick I don't know though. I don't have a subdomain multisite to check: there may also be paths in wp_X_options you'd need to change: you may need to debug through the bad state to work out what's going wrong.