Why not track uploads and ignore themes and update database with site URL?

I would appreciate clarification on this. Why view the themes any different than the plugins? They are in the same category of add-ons that can typically be replaced, depending on how integral the theme and plugin settings are to your site content.

There was a comment made back in 2014 about how the Bedrock themes directory is completely independent of Composer, but if that’s true then it’s just as so for plugins. They appear to be managed very much the same as package types associated with a directory under wp, so maybe that was the case back then?

The data that fundamentally differentiates WordPress sites are the database state and any other theme/plugin or core-created (what Scott refers to as “user generated”) files, which are exclusively media files saved in the uploads folder. As Bedrock’s docs mention, some plugins, and hopefully not too many themes, create files in other places. The WordPress developer community encourages theme/plugin authors to save persistent data in the database exclusively, favoring the Settings API, but otherwise in the uploads folder if need be, preferably as media attachments or in a folder named after the plugin.

As a result, unless the theme/plugin doesn’t adhere to this good advice, you can expect the uploads folder to be the only place that has data that must correspond with the database in order to not deploy a broken site. It is unclear why Bedrock treats the themes folder like it should be treating the uploads folder.

Also, I would like to try Bedrock and Trellis in a moment here, but I’d like to know where Trellis is on the situation of updating the database with the environment’s site URL in a way that preserves serialized PHP data, as that’s the only way to save your database as SQL that refers to some URL quite a few times in the most random places across different environments with different server names which must be changed from the static database export. There is another thread here discussing various techniques. I recommend, if possible, updating Trellis to require wp-cli so as to use the search-replace command, even if some other features may be redundant.

I really hope Bedrock has been updated to handle searching and replacing the site URL in the database correctly because this problem is why I created some WordPress git hooks some time ago. I first thought VersionPress was the better solution, but the Root tools are far more comprehensive and what have been missing for some time.

In short, I’d like to engage in a discussion about the benefits of treating the uploads folder and database state (as imported SQL or what have you) as the site’s independent content as opposed to the themes folder, which should be treated as untracked environment-specific files like the plugins. I can change the Bedrock project’s .gitignore but I was hoping to have a discussion with Roots developers, which might be more involved down the road as I try to get some changes upstream.

I’m a little confused with what changes you’re proposing. Do you want themes to be untracked in Git and treated like plugins? If so, here’s my thoughts on that:

A WordPress/Bedrock site represents a web application. We here at Roots believe that the theme (views in other frameworks) are part of that application so that’s why it is tracked as part of the same Git repo by default.

If you look at other frameworks like Ruby on Rails, Laravel, Django, etc, they all treat things in a similar way. Obviously WP has differences like storing URLs in the database, but that doesn’t change the overall strategy.

There’s no reason for us to change this default. If someone wants to have their theme as a separate package, they are free to do so and it’s very easy to do.


Neither Bedrock nor Trellis handle databases between environments. There are too many workflows between people to assume one for the majority. The threads you linked are the solutions that people have come up with for their own workflows and have shared.

So, basically, any database moving/syncing is up to each developer, there’s nothing by default. Since it is different for everyone, I don’t know if a default would be added in. Some people are able to just push their database up to staging/production. That really only works if they’re the sole developer/content editor. Otherwise, generally staging/production are the place where others modify content, so the developer(s) need to pull the database down.

I don’t know if it’s a specific “no” that Trellis won’t support this. I think the thing is that a database dump and downloading the uploads directory isn’t super difficult. There are already WP plugins and tools that handle it for you as well. I believe there are even some Ansible playbooks on Ansible Galaxy that sync databases.

It wouldn’t be especially difficult to set this up as an Ansible role, in fact it might already be done, I haven’t followed along completely with people’s updates on that. It would need to be an extra playbook though, as it definitely could not be baked into the deploy role.


Thanks a lot for the very quick and informative responses! I had a lot of information in one post, so I apologize if there was a lot to unpack. Also, just realized this post was mis-titled! It meant to ask why not track uploads and ignore themes.

I appreciate Scott clarifying the position of Roots on tracking themes. I can see why you would see them as views such as many other MVC frameworks. It’s just that WordPress doesn’t seem to follow that approach all too strictly, or even all that consciously. For one, your “model” data isn’t really concise data that is just in the database, but is typically database data that corresponds with files. Also, with their system of filters, actions, content types, meta content, etc. it is clearly a full-fledged web application of its own rather than a stripped down framework with succinct models, views, and controllers. Even though when WordPress is stripped down, you can define the content types in any way you choose, there are very specific filters that change text and actions performed at certain times to hook into rather than a direct manipulation of model data like the frameworks cited.

WordPress seems to be a different kind of thing where if you were to associate the MVC framework to it, you might boil it down to site content which again is not just in the database but shares its state with that uploads folder, most typically, as well as “controllers” that would have to include both the themes and the plugins as they both produce views in the same sort of way, even if you might associate the visual aspects of a view with that of a WordPress theme. More fundamentally, the plugins and themes are means to effect the filters and actions and other opportunities to run custom code.

Also, you would untrack both themes and plugins for the same reason of not tracking composer packages in general because the code is already tracked and you are just downloading it to your project.

Anyway, it would be great to have more of a discussion on this, but I’m glad that I can at least change the local .gitignore, except I’ll have to keep that in mind when I want to update Bedrock in a project.

Regarding database deployment, I should note Trellis does provide some means to handle databases between environments in the wordpress_sites.yml. According to this page, the db_import key can be set to a SQL file that will be imported. I’m not sure at which stage in the deployment flow, but looking at the hook variable section I’m hoping that the logic in my Git hooks would be better applied here, but I’d still want to use wp-cli for searching and replacing the DB properly, as well as the weird extra step for multisite.

Okay, yes there is a lot to work with here and I really think this is one of the best solutions for deploying a Wordpress site smoothly across environments. My only critique is that it should be more cognizant of the content that distinguishes WordPress sites which is really that database and uploads folder whereas everything else can be brought in from libraries. It is the site definition and content that the Bedrock project should really be tracking, and then it provides a means to download the core files and add-ons. My git hooks do that very thing and work with any site I’ve thrown at it so far, and I’m glad that Bedrock can be made to untrack the themes and handle them just like the plugin dependencies.

So I guess I would expect to edit that .gitignore and then find the best place to do the DB search-replace. I know there are different approaches and philosophies, but it really seems to make the most sense to track the uploads and DB state with your project, because the themes/plugins defined in it are integral to it. They seem to relate to each other very strongly. Then again, you could track them in a separate repo and take note of which version of the content repo corresponds with your Bedrock repo. Syncing the database across the machines is all well and good, but you’d have to have a corresponding uploads folder with each database state. The first approach seems the more natural and simplest, I suppose, but I don’t deny the benefits of these other techniques.

Thanks again for helping me better understand why the system is setup in this way. I will dive more into Bedrock and hopefully discover some Ansible playbooks or other hooks for smooth database deployment across environments.

Trellis offers deploy hooks so you could easily run WP-CLI (which Trellis includes) to do various tasks such as a search and replace on the DB as part of your deploy.

As a designer/developer my workflow for every single Wordpress website I create is to build a custom theme specific to that site. So for every Roots stack build I’ve done it only has one theme, and that theme was only created to show that database’s content.

But that’s just me, not for everyone.

1 Like