Managing Your WordPress Site with Git and Composer Part 1 – Storing WordPress in Git

Welcome to the first post in a series on Managing Your WordPress Site with Git and Composer. Together we’re going to look at how you can store WordPress in Git and how you can manage the parts of your WordPress site that shouldn’t be stored in your Git repository (e.g. themes and plugins) using Composer or Git Submodules.

At first we will simply store WordPress in Git as an introduction to using WordPress with Git, however later in the series we will cover the more complex, but arguably better approach to managing WordPress core itself using Composer or Git Submodules.

Why Git?

Version control systems like Git have become a huge help to developers in recent years, allowing collaboration on a level that previously just wasn’t possible. However it’s not always easy to get started using Git, especially if you’re trying to work with a big, established project like WordPress.

However the benefits of learning how to manage your WordPress site using Git are huge. Not only can you use awesome Git features like rolling back breaking changes and using branches for bug fixes and feature builds, but you can use amazing apps like GitHub to store your site and Dploy to deploy changes to your site with one click.

In this series we will approach most aspects from a beginner point of view, however I am going to assume you have a basic knowledge of Git and Composer and are comfortable using the command-line.

So, without further ado, let’s get going.

Storing WordPress in Git

To begin with we are going to store the WordPress core itself in Git. While it might make more sense to store WordPress separately using Composer or Git Submodules, that gets a bit more complex and involves changing the structure of your WordPress site, so we are going to leave that for a later post. For just now we’re going to focus on getting WordPress up and running and stored in Git.

Let’s start from scratch and create a new folder that will contain your WordPress install (or you could copy your existing WordPress site into a new folder if you wanted to). Open up Terminal, or whatever command-line client you use, and run:

mkdir wpgit && cd wpgit

In this tutorial we are going to use a relatively new project called WP-CLI. WP-CLI is a set of command-line tools that can help you manage your WordPress installations. For example you can update plugins, setup multisite installs and much more, without using a web browser. If you don’t have WP-CLI installed you can follow the installation instructions here.

So let’s download and install WordPress using WP-CLI. If you’ve copied over an existing WordPress site (or you don’t want to use WP-CLI) you can skip this bit.

wp core download
wp core config --dbname={YOUR DATABASE NAME} --dbuser={YOUR DATABASE USERNAME} --dbpass={YOUR DATABASE PASSWORD}
wp core install --url={YOUR DOMAIN NAME} --title={THE TITLE OF YOUR SITE} --admin_user={YOUR USER NAME} --admin_password={YOUR PASSWORD} --admin_email={YOUR EMAIL}

install-wordpress-cli

Next we need to make our WordPress install a Git repository. This is as easy as running:

git init

At the moment your new Git repo will be empty as we haven’t added any of our WordPress files to it. That’s because there are certain files and folders that we don’t want to add to the Git repo. This is because some folders might change often (like plugins and themes, we’ll be looking how to manage plugins and themes outside of Git in a future post) or your files might contain secure information (like database passwords).

Thankfully Git has a handy way of dealing with this problem. By creating a .gitignore file you can specify which files and folders you want to exclude from Git. Let’s do this by creating and editing the .gitignore file:

touch .gitignore
nano .gitignore

We can add rules to the .gitignore file to tell Git to ignore certain files and folders. Add the following rules to your .gitignore (lines starting with a # are comments):

# Ignore wp-config.php and .htaccess
wp-config.php
.htaccess

# Ignore the wp-content directory
/wp-content

gitignore

Note that you can, if you want to, add certain plugins and themes to the Git repo by including the path to the plugin or theme. For example:

# Don’t ignore plugins dir, but ignore everything inside
!/wp-content/plugins
/wp-content/plugins/*

# Don’t ignore akismet plugin
!/wp-content/plugins/akismet

Save the .gitignore file. As all “user managed” files (e.g. plugins, themes and uploads) are stored in the /wp-content folder, it’s easiest to just ignore the whole folder.

Now we’re ready to add the rest of our files to Git. We can add our files and commit them by doing:

git add .
git commit -m "Initial commit"

Great, you now have a WordPress site stored in a Git repository. There are a couple of things to remember when using this method:

  • It’s best practice not to store secure information (like database passwords) in a Git repo (hence why we ignore wp-config.php). This means you’ll have to deploy wp-config.php manually.
  • Everything in the /wp-content folder won’t be stored in Git (plugins/themes/uploads etc.) so if you’re deploying or migrating your site remember to manually migrate these files.
  • The database won’t be stored in Git, but don’t worry WP Migrate DB Pro has you covered 😉
  • If you update WordPress locally, you’ll need to commit the changes to your Git repository. Be aware that when using this method WordPress will disable automatic updates (because it will detect a .git folder). This is good as it means there is a one-way deployment of updates to your site (rather than your live site becoming out of sync with your Git repo) as long as you are aware keeping your site up-to-date is important for security reasons. But we’ll talk more about this in a later post.

That’s it for part 1. In the next post we’ll be looking at how to use Composer to manage your plugins and themes for your Git stored WordPress site.

About the Author

Gilbert Pellegrom

Gilbert loves to build software. From jQuery scripts to WordPress plugins to full blown SaaS apps, Gilbert has been creating elegant software his whole career. Probably most famous for creating the Nivo Slider.

  • Patrick Gilmour

    Really looking forward to this series of articles – thanks Gilbert. Already learned a lot!

  • mdfonda

    Have been looking to get into this type of workflow, but finding solid resources that address it from a beginner perspective have been hard to find. Very much looking forward to the rest of this series.

  • mbm

    Really looking forward to seeing how you use Composer for plugins and themes.

    I had basically always done git repos the opposite for WordPress installs. I use git for source control of the key wp-content directories, e.g., themes and plugins (or any other directories I need, but not uploads or static media). This way, I track theme and plugin changes but can still use the WP updater to handle core updates, which are a lot less volatile than the code that I’m writing in my themes or plugins.

    What my method lacks is a way to truly sync from a remote repository to a production server, so I’d usually use an rsync command to mirror out any changes files to production and mostly use my git history as a QA to make sure everything that went out was supposed to go out.

    Really looking forward to the rest of this because I’ve wanted to overhaul my workflow.

    • If that workflow works for you there is nothing wrong with it. I’ve actually done something similar in the past. It depends on what you are trying to achieve. Being able to deploy to a production server from a repo is a big win for this type of workflow.

  • timichango

    See — what I find weird about this approach, is that it’s more or less the inverse of what I’m trying to accomplish (and what I’ve seen/read/heard elsewhere to be a better approach).

    Given that the vast majority of folks who’re bothering to version control wordpress site development area also very likely developing custom plugins/themes, the following would seem to be a more beneficial structure:

    1) ONLY have your custom plugin/theme code in the repository (along with any configuration code required to create/provision/configure the environment).

    2) Bring the environment and any 3rd party code (eg. non-custom plugins) in as dependencies. Also *bring wordpress itself in as a dependency*

    3) use technologies like puppet/bower/composer/gulp/etc. to accomplish step 2 based on configuartions stored in the repository.

    Historically I’ve been keeping the whole site + dependencies (and I consider WP to be a dependency) in git, but to me, given that the majority of what winds up being custom lives within the wp-content folder (ie. the actual work we’re doing is theme/plugin work), your approach here — that “Everything in the /wp-content folder won’t be stored in Git” — totally bakes my noodle. It doesn’t make sense to me to aim to store generic WP core files in the repo, but deliberately exclude the customization work we’re actually undertaking.

    Help me understand the rationale and/or use-case?

    • I totally agree with you. Thats why later in this series I’ll be looking at how to use WordPress Core as a dependancy 😉

      Storing custom themes/plugins in Git makes sense, but I’d still argue almost everything else (in wp-content) shouldn’t be stored in a repo as it should not be tied to deployment. Things like file uploads, caches etc. just take up space in a repo and don’t belong there. Non-custom themes/plugin should be added as a dependancy, which we’ll look at in the next post.

      • Christof Coetzee

        I dont agree, the ONLY code that should be in the repo is your custom plugins, themes etc.
        In modern applications (unlike WP) you have ‘vendors’ as 3rd party code, which you never EVER keep in your repo.
        During deployment you will run Git to pull down your app and then use tools like Composer to install these vendors.
        In fact I think WP is too much of a spaghetti mess to utilize modern version control and deployment methods the correct way.

    • Anoop Divakar

      While going through this post my thoughts were the same …… I have seen some posts that describes wordpress as a git submodule ……. What i usually do is take wp-content out of wordpress , have a conditional config ( development, staging and live ) and push the current theme commits only , which i find much more easier to maintain.

  • timichango

    Additionally: there seems to be an argument to be made FOR sticking even 3rd-party code into the repo. If you disable auto-updating of 3rd party plugin code on the production side (a whole other topic), then the repo — and whatever updates it has applied to it — remains the authoritative state of the site. If we omit those dependencies and tie those dependencies to external repositories (eg. the wordpress plugin repo), I’d imagine that you’d wind up introducing potential volatility if/when something like composer runs off and provisions a new version of that 3rd-party code that introduces breaking changes.

    Thoughts?

    • For me this comes down to preference. If you want to have an “authority” repo which is an exact representation of your production server, then add 3rd-party code. However for most people I imagine it would be cleaner and simpler to just add dependancies and manage updates manually.

  • I can tell excluding plugins from git is a good idea because their updates can really blow up your repository size. I’ve had a project running over 1,5 years with about 40 active plugins that I would update every week or so. The whole git repository ultimately grew to 300 MB which is tedious to work with especially if you want to quickly onboard new developers or setup alternative installs. And figuring out how to downsize a git repo is not for the fainthearted either, so at one point I just reinitialized the repository leaving behind 1,5 years of dev history.

    Today I’m using composer to install plugins on deployment but that’s also not easy since many premium plugins are not publicly accessible and need to be added to the repo therefore. Deliciousbrains is a notable exception here: you can add your license key to the download URL and that will give you a valid download of the plugin.

    • Yeh space can be a big issue when storing everything in Git. Premium plugins can be an issue if the developer doesn’t support valid downloads and updates, but there is nothing you can do about that unfortunately.

      • I’ve now refined it so that we only store the composer.json file, and a couple of control files (.htaccess etc.) in Git with composer handling all dependencies (including WordPress!) either from wpackagist (which mirrors all WordPress.org components) or a self-hosted Composer repo. Gets around the paid plugin issue.

  • Really interesting post. I’ve been looking at jumping into version control for the WP install at my day job. Having 3-4 different contractors working on the site at any given time makes troubleshooting a bit of a headache. I was looking at WP Pusher to just keep themes and custom plugins in Git repositories, but had never thought of applying these principles to the whole site. Looking forward to the upcoming posts on how you make this work.

  • Hey Gilbert nice set of series. But one question, why would anyone want to store WP in Git? I mean if you developing theme or a plugin, just using Git for them is enough. Why upload WordPress to Git?

    • If you want to deploy your entire WordPress site from a hosted repo to a production server, for example, then you would need WordPress stored in your repo.

      • Yup that makes sense.

      • We just use Scriptaculous to create a raw install, import a database backup (using WP Migrate Pro), and check the wp-content directory out of git. I haven’t read the rest of these posts, but checking WordPress into a git repo just seems wrong unless you’re mirroring the WordPress repo and selecting a particular revision from a central repo which might make some sense in some cases.

  • Jake Jackson

    If you want a full-blown version-controlled composer stack with deployment I’d strongly recommend Bedrock, by roots (https://roots.io/bedrock/ ). It will save you hours trying to set this up and we use it daily to easily make changes and deploy / rollback changes.

    • Every time I look at Bedrock, I marvel at how complicated they’ve made a fairly straightforward process.

  • Jonathan Nicol

    The approach advocated by this article seems counter intuitive. The WordPress core is a third party dependency, so I’m not sure what benefit there is to keeping it under version control? In my workflow I use Git to store custom code, which in the case of a WordPress site is the site’s theme and any site-specific plugins, but the article recommends excluding the wp-content directory from Git. What is your rationale for keeping your custom code outside of Git?

    • So if you want to deploy your entire WordPress site from a hosted repo to a production server, for example, then you would need WordPress stored in your repo. Storing custom code makes total sense and thats exactly what Git should be used for. However things like file uploads, caches etc. just take up space in a repo and don’t belong there. Non-custom themes/plugin should be added as a dependancy, which we’ll look at in the next post.

      • If you don’t store uploads, how does the media library get filled?

        • Travis Miller

          It doesn’t. Media files are content, just like posts. They aren’t part of the application, and therefore shouldn’t be included in version control.

          If you’re trying to keep content in sync (e.g., between dev and production instances of a site), then you probably want a tool other than version control.

  • Bharat Singhal

    Thanks for the nice article, but one question I have is that if I install wordpress on a PaaS server then installing plugins on the live website through GUI will not be persistent of the server is rebooted, so how to manage wordpress as a whole with git?

  • I’ve used WP Migrate DB Pro for about 2 years ever since you sponsored a ShoptalkShow podcast and it totally changed my dev workflow. Now I’m finally getting onto the GIT and WP bandwagon and this post is excellent. I’ve also used WP Offload S3 recently and I have to say that your plugins are amongst the best I’ve used. Thanks so much for writing this tutorial.