Rolling Back / Reverting Changes to Your Theme Using Subversion

You can access your theme repository version history and, when necessary, quickly roll back your deployed theme to a previous state.

The Time Machine

Every time you commit a change to your theme to your VIP theme repository, Subversion remembers by creating a version. Each of these versions is assigned a unique number and certain other meta, namely: the username of the person who made the version, the date and time of the version, the number of lines of code changed in the version relative to the previous one and a commit message indicating the nature of the changes in the version.

You can inspect your theme’s version history on the command line using the svn log command (documentation: clitortoiseSVN.) Here’s some sample svn log output for Automattic’s test theme on VIP:

vip/test-theme$ svn log .
r69251 | viper007bond | 2012-06-20 21:09:52 +0000 (Wed, 20 Jun 2012) | 1 line

Remove testing code
r69209 | batmoo | 2012-06-20 13:59:49 +0000 (Wed, 20 Jun 2012) | 2 lines

auto-deploy: rm image in a subfolder
r69197 | batmoo | 2012-06-20 13:40:55 +0000 (Wed, 20 Jun 2012) | 2 lines

Auto-deploy: testing a php + css commit
r66930 | tottdev | 2012-05-27 11:19:52 +0000 (Sun, 27 May 2012) | 1 line

reverting error code

To inspect a commit in more detail (such as seeing the changes it introduced), svn provides the svn diff command (docs: clitortoiseSVN.) Here’s an example:

vip/test-theme$ svn diff -c 17546 .

Index: header.php
--- header.php	(revision 17545)
+++ header.php	(revision 17546)
@@ -6,7 +6,6 @@
-<meta name="generator" content="WordPress "/> 
 <link rel="stylesheet" href="?2" type="text/css" media="screen" />

The -c flag shows a change set resulting from a single revision, but there are many other options including -r n:m (show differences between revision n and m) and more — see the svn diff documentation for full details.


If you need to roll back code you’ve committed it to the deploy queue, the quickest way to do this is to revert and commit the code yourself. Here’s how to prepare and push a roll-back:

1. Update your theme’s working copy to the latest revision (use

svn up your-theme

or tortoiseSVN.)

2. Use svn log to find out how far you’d like to roll back. Suppose your log reveals something like:

r4 -- change paint color
r3 -- introduce clunk engine
r2 -- modify blee tag
r1 -- add snorkle

3. Use svn merge to roll back the code to the revision before things went ‘wrong.’ For example, a typical cli command for this would be:

vip/my-theme$ svn merge -c -4 -c -3 .

This “un-does” the commits with version numbers 3 and 4, and rolls the code back to its previous state as of revision 2. As with svn diff, the merge command admits lots of different syntax combinations. You can read about some of those here and here. You can also roll back easily using clients like tortoiseSVN.

4. The merge you just performed has produced a changeset in your working copy. Commit your roll-back like any other change using svn commit.

Make sure that you include an explanatory commit message such as “roll-back of r3 and r4 due to JS error”. Your message should indicate which versions are being rolled back, and for what reason. This will help VIP deploy engineers quickly deploy your changeset.

Pure roll-backs usually require little or no review, and can be deployed almost immediately, so make sure your change only contains the roll-back, and nothing else.

In an emergency situation, you can open an urgent ticket requesting a deploy of your roll-back. Generally this is not necessary, however, and we request that you reserve urgent tickets for when your site is down or for other serious end-user issues.

Best practices:

1. Think in terms of “rolling back” code instead of reverting individual commits. It’s possible to revert things out of sequence. For instance in the previous example we could have reverted r3 but not r4. However, to do so ignores the possibility that something in r4 may depend on something in r3. In almost all cases, it’s safer to roll back all commits in sequence, especially if doing so quickly.

2. Data dependencies. Before a major roll-back it’s good to take a second to consider whether the underlying data has changed in a way that would cause problems with the old code. Have the content or options been modified in any way, including by CLI scripts? This is not usually an issue, but can be in certain cases.

3. Confusingly, subversion also features a command called svn revert whose purpose is not to take your code to a previous state, but only to un-do local un-committed modifications. Therefore we use the term “revert” both in the sense of “roll-back” and the sense of svn revert.

4. Finally, There is an extremely large number of Subversion clients which make all of this very easy. Cornerstone is a great (though somewhat expensive) client for OSX.

VIP Quickstart

Note: VIP Quickstart is deprecated as of March 13, 2017. Support for Quickstart will continue through April 21, 2017. For new environments, we recommend using Chassis or VVV as detailed in the Local Environment documentation.

VIP Quickstart is a local development environment for VIP developers. It provides developers with an environment that closely mirrors along with all the tools we recommend developers use.

VIP Quickstart should not be used to run a production site.

See also: The VIP Quickstart Github repository.



Public Server

  • Tested with a host running Ubuntu 12.04
  • Git
  • Puppet

Getting Started

Installing locally for local development (primary use-case)

The first time you run the installer will be the slowest. This is because it has to download the virtual machine image, Ubuntu package updates, wp-cli, the full checkout of WordPress trunk, and the full VIP Plugins repository.

  1. git clone --recursive
  2. Use Zeroconf or set “ vip.local” in your /etc/hosts file (path varies by platform)
  3. Change directory to the vip-quickstart directory: cd vip-quickstart
  4. Run vagrant up
  5. Get a hot/cold drink, wait ~10-15 mins depending on your download bandwidth
  6. When the install completes, load http://vip.local in your browser, login with username: wordpress, password: wordpress

Have problems installing? See Installation Tips below

Installing on a publicly accessible host for content staging, qa, client preview, etc (secondary use-case)

  1. Add user with SSH key
  2. Install Puppet and Git
  3. git clone --recursive /srv
  4. sudo /srv/bin/vip-init --server [--domain=<domain>]

If you specify –domain this will set up the Quickstart environment as ready to serve requests at that domain. You are responsible for making sure that DNS for that domain points to the IP address of your server.

If you leave the domain argument off, you’ll be prompted to enter one during setup. If you don’t specify one then, “” is used by default, and you can work with your local DNS/hosts setup to make sure that points to the right place.

Since we turn off root logins and password logins via SSH, you’ll need to create another user and add an SSH key so you don’t get locked out of your server. ssh-copy-id is useful for copying ssh keys on Linux. There are similar tools for other platforms.

Installing on Windows (minimally supported use case)

  • Note: When you run the Git installer, make sure to install Git to your system PATH as the VIP Quickstart installer requires it.

  • If you receive a File cannot be loaded because the execution of scripts is disabled on this system error. Make sure you’re using a PowerShell interface. Use tools -> options to manage your default shell. (Right click on the repository and choose “Open a shell here”)



Zeroconf is built-in to OS X and shouldn’t require any configuration.


If you have iTunes, you already have this. Otherwise, you need to install Bonjour.


sudo apt-get install avahi-dnsconfd

Optional JS & CSS Concatenation Configuration

  • QUICKSTART_DISABLE_CONCAT – CSS and Javascript concatention are turned off if this is true.

Default Usernames and Passwords


  • root:(blank)


  • wordpress:wordpress

Upgrading Quickstart

You can upgrade an installed environment with:

  • git pull
  • vagrant provision (assuming Quickstart is already running)

If you experience issues upgrading, you may delete it and start fresh. You can do so with: vagrant destroy; rm -rf vip-quickstart , re-install per above instructions and restore your site from version control and backups.

Vagrant Primer

The Vagrant CLI documentation will be useful for developers that haven’t used Vagrant before. Since VIP Quickstart is built on top of Vagrant, the Vagrant CLI commands will also work.

Some useful commands:

  • vagrant up – Start and provisions the VM
  • vagrant halt – Stops the VM
  • vagrant reload – Restarts and provisions the VM
  • vagrant provision – Provisions the VM, requires that the VM be running
  • vagrant status – Reports the state of the VM
  • vagrant ssh – Logs into the VM with ssh
  • vagrant destroy – Deletes the VM

Enabling and Activating a Custom Theme

In order to use a custom theme in VIP Quickstart, move a valid WordPress theme folder into this directory:


Once the theme is in the correct directory, you can “Network Enable” it from this page:


From there you should be able to activate it on individual sites.

Loading Plugins

To approximate the admin interface on, Quickstart does not have a Plugins admin menu section. Instead, you can load plugins via your theme code (usually in functions.php).

Any plugin available in the VIP shared plugins repository can be loaded with a call to wpcom_vip_load_plugin. That function will work on Quickstart and If a plugin is in the VIP plugins repository, you should not copy that plugin into your theme.

To load a plugin not in the VIP shared plugin repository, take a look at how to load plugins in different locations.

We advise against any logic that makes functionality exceptions for your development environment; development and production environments should be as close as possible to avoid unexpected production-specific issues.

Flushing Permalinks

The permalinks settings pages is not available in the admin area, but if rewrite rules need to be flushed or changed, this can be done in code. To flush rewrite rules, we recommend using the WP CLI command wp rewrite flush.

You can also use WP CLI to set the permalink structure and tag/category base using the wp rewrite structure command.

Importing Content

The best way to import content into a Quickstart site is to SSH into the Vagrant VM and use the ( command. It’s helpful to first move the import files into the vip-quickstart directory.


VIP Quickstart does not include a copy of phpMyAdmin, since we do not recommend using this tool for making changes to the MySQL database as a part of your development and testing work. Instead, use WordPress’s built-in functionality and API to query and manipulate data according to our best practices.

Unit Testing

VIP Quickstart comes with a checkout of the WordPress-Tests automated testing framework. You can use this to run the unit tests for WordPress itself or for any plugin or theme that has phpunit tests defined.

To run the WordPress unit tests

  • CD to /srv/www/wp-tests from within the VM.
  • Run phpunit

To create unit tests for your plugin/theme

  1. Navigate to your theme or plugin within the VM. (eg. /srv/www/wp-content/plugins/my-plugin)
  2. Use WP CLI to the generate the plugin test files. Eg. wp scaffold plugin-tests my-plugin
  3. Run phpunit inside your theme or plugin directory.
  4. Start building your tests within the newly created tests directory.

Differences between Quickstart and

While we created Quickstart to mirror the environment as closely as possible, there are some key differences to be aware of:

  • There’s currently no support for SSL on Quickstart.
  • If you install Quickstart on a VPS that’s publicly accessible, you can take advantage of Photon, which is similar to the CDN used on If Quickstart is only local, you’ll be limited to the local Media Library.
  • Some toolbar modifications on are not yet present in Quickstart.
  • Database encoding on is latin1. On Quickstart, it’s utf8.
  • Protected embeds are not yet supported on Quickstart.
  • Filesystem access is not yet fully restricted in Quickstart as it is on
  • There may be minor version differences in some libraries, such as jQuery.
  • When options are added or updated on, we delete the alloptions cache. This is not the case on Quickstart so, for instance, you may see `get_option()` return booleans that would return a string on Always assume that `get_option()` will return a string.

If you’d like to help minimize these differences, you can view the list of compat issues on GitHub.

Installation Tips

Q: My installation completed, but I see an error “The SSH command responded with a non-zero exit status…”
A: That’s normal, try loading http://vip.local in your browser or try vagrant ssh from the vip-quickstart directory to login to the virtual machine. If neither work, try vagrant status to ensure the virtual machine is running.
Q: When I open http://vip.local in my browser I get a blank screen/500 error
A: Enabling WP_DEBUG in local-config.php should reveal the PHP error, xdebug is also installed and enabled
Q: Installation is failing on provisioning, and I’m not sure what more to do
A: You can run vagrant in debug mode to get more information, including error messages you wouldn’t normally see. To do this run this command:

vagrant up --provision --debug &> vagrant.log

Also make sure you have the latest version of virtualbox, vagrant, and the vagrant box being used. As a last resort, these commands will wipe everything clean and recreate everything:

vagrant destroy
vagrant box remove precise32
vagrant plugin install vagrant-hostsupdater
vagrant plugin install vagrant-triggers
vagrant plugin install vagrant-vbguest
vagrant up --provision

The vagrant hosts updater may require your hosts file to be writable. If provisioning fails or is interrupted, try this command:

vagrant reload --provision

This will resume provisioning without destroying the box

Q: I’m getting “Error establishing a database connection”
A: Provisioning may have been interrupted, try running this command several times to ensure it completes:

vagrant reload --provision
Q: Several VIP functions are not being found and giving fatal errors
A: These functions are loaded when `vip-init.php` is included. This file should be included at the top of the themes `functions.php`, and this will show as a blocker when the theme is scanned by VIP Scanner. Make sure to run VIP Scanner and clear all blockers, and include `vip-init.php` as a priority.

Anatomy of a VIP Theme

This page explains the anatomy and structure of an example theme that might be used on VIP. It complements the Theme Handbook that apply to regular WordPress theme development. While every client’s themes will have different requirements and constraints, following this general structure will help ensure faster theme reviews and more efficient long term maintenance of your site.

Theme Naming

Themes in the VIP environment live in WP_CONTENT_DIR . '/themes/vip/'. So if your organization is called Acme Kite Co., for example, your theme path might be /wp-content/themes/vip/acmekites/.

If you anticipate setting up multiple themes for your site or if you are a developer working on different themes for different sites, you might need a naming scheme that further distinguishes themes, e.g. /wp-content/themes/vip/acmekites-main/ and /wp-content/themes/vip/acmekites-seasonal/.

Plugin Locations

Each theme should have a dedicated directory for custom plugins:


You can then load a plugin from this directory with:

wpcom_vip_load_plugin( 'plugin-name', 'theme' );

If you are developing plugins that might be used across multiple sites/themes, you can put them in a plugins directory not associated with a specific theme:


Plugins managed this way will live in a separate SVN repo and loaded using wpcom_vip_load_plugin:

wpcom_vip_load_plugin( ‘plugin-name’, ‘acmekites-plugins’ ); // note this requires a specific naming structure: /plugin-name/plugin-name.php

There is also a directory for plugins shared across all VIP sites, make sure you avoid this directory namespace in your development structure:


Plugins available to all VIP sites can be loaded using wpcom_vip_load_plugin as well:

wpcom_vip_load_plugin( ‘plugin-name’ );

Child Themes VIP sites can create and use themes that are child themes of the themes available on This allows you to build on the great themes already developed and tested for WordPress while incorporating your own custom features and styles. When the parent theme is updated or expanded, your child theme can take advantage of those changes without having to re-incorporate your customizations. Child theming works the same in this case as child theming on self-hosted WordPress sites. Each child theme is managed in its own SVN repository.


The functions.php file in your theme lays the groundwork for customizing the functionality of your theme.  You can read more about it in Functions File Explained. On VIP sites, the functions.php file must include the vip-init functions.  

It is critically important that `vip-init.php` is included very early in `functions.php` – before any VIP constants or functions are used.

Here’s a sample VIP functions file for Acme Kites:


// Set a theme constant for later use

* Standard VIP configuration
require_once WP_CONTENT_DIR . '/themes/vip/plugins/vip-init.php';

// Site-specific Config
require_once(AK_DIR . '/functions/config.php');

// Custom widgets and sidebars for this site.
require_once(AK_DIR . '/functions/widgets.php');

Use Underscores for a head start

The Underscores project will generate a starter theme that can be used to get a head start on your theme development. It includes lean, well-commented, modern, HTML5 templates, minimal CSS that’s ready for you to build on, and a variety of tools to help you work efficiently in customizing your theme.

See Also

Related Posts

You can take advantage of the Related Posts functionality to return related posts quickly. Enable it by turning on Related Posts in Settings > Reading and you’re done!

If you’d like to programmatically retrieve and display posts within your theme code, you can do so like this:

$posts = Jetpack_RelatedPosts::init_raw()->get_for_post_id( $post_id, $args );

// Returns an associative array in the form of id => $post_id:
    array ('id' => 12345),
    array ('id' => 54321),

Related Posts indexing will work regardless of whether your site is marked as “Private.” For self-hosted sites, Related Posts will currently only work for standard post-types; we are working on enabling it for custom post types.

For more information about ways to customize related posts, see

High Traffic Alert

On, we serve 100+ million pageviews per day without blinking. However, sometimes you may be expecting a high traffic event where you may want to notify the VIP team for additional assistance.

To do so, please open a ticket with us with the following information:

  • Date and time of event:
  • Traffic expected:
  • Heavily trafficked pages:
  • Are there any external services, dependencies, or applications that use or rely on the site (e.g. mobile apps)? If so, how do these services interact with the site?

On VIP, we review every line of code to ensure that your site will perform under high traffic events. When you send in a high traffic alert, we will check through the theme again to ensure that it is performance-ready. Please notify us of the high traffic event as far in advance as possible so that there is enough time to resolve any potential issues.

As always, should you need our team immediately, please open a ticket with the word “urgent” in the subject line.

Creating Good Changesets

Changesets are the heart of any version control system, and making good changesets is vitally important to the maintainability of your code. As all code on VIP is reviewed by a real person, it’s even more important all changesets are well crafted.

Remember always code (and commit) for the maintainer.

A Good Changeset:

Represents one logical change

What comprises a ‘logical change’ is up for interpretation, but only directly related changes are included. Generally, the smaller the changeset, the better.

Good Example: Adding the CSS, JS, HTML, and PHP code for a new UI button.

Bad Example: Adding the new UI button, fixing whitespacing, and tweaking copy in the footer.

Bundles related changes together

It’s much easier to trace refactorings and other changes if related changes are grouped together. Rather than splitting a logical change into many separate commits, related changes should be combined.

Good Example: Refactoring code into a new plugin by moving it to a new file and including that file.

Bad Example: Refactoring code into a new plugin by putting the code removal, addition, and include into separate commits.

Is Atomic

An atomic commit means that the system is always left in a consistent state after the changeset is committed. No one commit would cause the codebase to be in an invalid state. The commit is easily rolled back to a previous valid state, including all related changes, without the need to analyze the potential interdependencies of neighboring commits.

Good Example: Adding a new feature to the homepage by committing the HTML / PHP changes alongside the required CSS / JS changes, so there is never an incomplete state (HTML elements without styling) in the codebase.

Bad Example: Committing the HTML changes and requisite CSS / JS separately. The first commit represents an inconsistent state, as the feature can exist in the DOM without being properly styled.

Is Properly Described

Accurately describing the changes is very important for others (and future you) looking at your code. A good commit message describes the what and why of a change. Please see Writing Good Commit Messages for more information.

User_meta vs User_attributes

User Meta

As you read in our what we look for documentation, we don’t allow the use of user_meta. The reason for this is that is an incredibly large multisite and user_meta is all stored in one cache key. Therefore anything stored in user_meta will be loaded on every page load. Another reason is that as the user_meta grows to over 1MB it can no longer be stored in memcache.

User Attributes

User_attributes are a drop in replacement for user_meta. They perform in exactly the same way with the small exception that you cannot have multiple values for the same user_attribute meta_key. You can find the function declarations in vip/plugins/vip-do-not-include-on-wpcom/wpcom-functions.php. These are functions that imitate the behavior of user_attributes on your local dev environement. This means you can code against them without needing to have the cache or table schema that runs on

While the code you will see in that file looks just like a layer on top of user_meta on, user_attributes are stored in the cache on an individual basis and not globally. This means that requests to user_attributes by meta_key and user_id are cached individually and not grouped by user_id and loaded all at once per page load.

You can use user_attributes as a drop in replacement for user_meta. That means:

update_user_attribute( $user_id, $meta_key, $meta_value )

get_user_attribute( $user_id, $meta_key )

delete_user_attribute( $user_id, $meta_key, $meta_value = ” )

will all work as expected. Just remember, the meta_key are shared among all of so prefix them. As with user_meta you shouldn’t store large quantities of data (several KB), and lastly, since just like user_meta meta_key or meta_value on user_attributes isn’t indexed you shouldn’t query against them.

Custom Error Pages

We have error pages that are standard and served for all sites on, and as a VIP customer you can override these defaults and specify your own custom error pages instead.

Setting it up is simple: all you need to do is add a custom error page (a simple HTML file) to your theme.

The file needs to be located in a folder called “error-docs” and named “error-page.html”. Note that the file can only contain HTML and basic inline or remote-hosted CSS and Javascript.

I.e., from the root of your theme: ~/error-docs/error-page.html

Once you’ve committed the file to your theme, you’ll need to open a ticket with our team to notify us, so we can make some associated configuration changes on our end.

Editor’s Guide to VIP

Welcome to VIP!

We believe that VIP is a partnership between and some of the most high-profile, innovative and smart WordPress websites out there. We’re excited to have you here.

This page is to help managers and editors onboard their editorial team onto VIP. It includes information and resources to help you train your team. If you have any questions, please don’t hesitate to contact us through the VIP tab in your site dashboard.

Training Resources

Useful Features for Editorial Teams

Useful VIP Plugins for Editorial Teams

Advanced Features for Editors

Learn from WordPress Experts

Developer’s Guide To VIP

Welcome to VIP!

We believe that VIP is a partnership between and some of the most high-profile, innovative and smart WordPress websites out there. We’re excited to have you here.

This page is to help developers prepare their code for VIP. It includes information on how to set up a site on VIP, and how to communicate with the VIP team. As always, if you have any questions, please don’t hesitate to contact us through the VIP tab in your dashboard.

Getting Started

Quick Links

Important Documentation

Helpful Resources

Learn from WordPress Experts

Ready to get started?

Tell us about your needs

Let us lead the way. We’ll help you select a top tier development partner. We’ll train your developers, operations, infrastructure, and editorial teams. We’ll coarchitect your deployment processes. We will provide live support for peak events. We’ll help your people avoid dark alleys and blind corners, and reduce wasted cycles.