• Skip to primary navigation
  • Skip to main content
  • Skip to footer
  • Store
  • Support
  • Theme Documentation
  • My Account
  • Cart

9seeds

Building Custom WordPress Solutions | Plugin Development

 
  • Custom Development
  • Themes
  • Plugins
  • About
  • Contact
  • Blog

wordpress

Deploying to SiteGround via git push

Posted on October 20, 2014

Git push is the best thing for deployments since sliced bread. I don’t know if sliced bread was ever a deployment requirement, but trust me it’s good. I used to work at a company that used a similar stack (svn+rsync) to deploy. I’m glad to see many hosting companies getting on board with git-push. May you never have to use FTP again!

We have an account at SiteGround, which provides git push, but implemented in a different way than others like WPEngine. If you’re not careful with how you use it, it can lead to some strange results. I’d like to highlight some of the differences, so you don’t get yourself into trouble – especially if you don’t want core WP files to be under version control.

Navigating SiteGround’s cPanel

SiteGround uses the classic cPanel interface. To help you navigate, I’ve highlighted the areas of interest:

cPanel home

Creating a subdomain

If you haven’t done so yet, you may want to create a subdomain for your install. We use a single domain at SiteGround and put several WP installs using subdomains for testing purposes. Here’s what the subdomain configuration looks like:

cPanel subdomain

If you’re setting up a WP install using your main domain name, you can skip creating a subdomain.

Creating your WordPress instance at SiteGround

When you go to add WordPress to your domain through cPanel, you’ll be using a tool called “Softaculous.” Click the big blue Install button to get started:

cPanel new install

Select the domain (or subdomain) that you want to turn into a WP install.

Remember to change:

  • Database name – it will be auto-generated, I tend to choose something that matches the domain or subdomain so it’s easy to remember what it goes with.
  • Table Prefix – I use the normal wp_ – I think changing this has become “security through obscurity” and if you don’t keep your site up to date, this is unlikely to save you from an attack.
  • Admin Username – replace the auto-generated username with something useful, but avoid admin since it is easily targeted by attackers
  • Admin Email – replace the auto-generated one with a real email address for the site administrator.

When the installation is done, to exit Softaculous and get back to the regular cPanel, just click the My Accounts tab at the top and then click the red Go to cPanel button.

Creating the git repository at SiteGround

Click the SG-Git icon on from cPanel. You’ll be brought to a screen where all of your WordPress installations are displayed, and if they don’t have git repositories associated with them, you’ll be given the option to create one. When you click Create Git Repository for your WP install, a dialog will come up with some git information. Record the git clone command, we’ll use it later.

cPanel git info

There will also be a SSH key and possibly the passphrase that goes along with it. Rather than using this key and sharing it with all the developers who you want to be able to push to this SiteGround account, I find it easier to add individual keys via cPanel.

Setting up SSH keys and config

SiteGround only takes DSA keys for SSH. If you don’t have an id_dsa.pub file in your ~/.ssh directory, you can create one by opening a terminal and running:

ssh-keygen -t dsa

Once your DSA key is generated, you can add it to the SiteGround control panel by clicking the SSH/Shell Access icon in cPanel. Copy the contents of your ~/.ssh/id_dsa.pub file and paste it into the text area on SiteGround:

cPanel ssh key

Some git clients won’t accept the fact that SiteGround uses a non-standard port for SSH. The way to get around this is to create a ~/.ssh/config file with an entry for SiteGround. If the git clone command SiteGround supplied looks like:

git clone ssh://[email protected]:18765/home/sguser/public_html/git

Then your ~/.ssh/config file should contain:

Host mXX.siteground.biz
        HostName mXX.siteground.biz
        Port 18765
        User sguser

Replace the Host, HostName, and User values with those from your account. I’ve changed them in this example for security purposes. To test you should be able to:

ssh mXX.siteground.biz

Notice you shouldn’t have to supply the username or the port, my ~/.ssh/config takes care of that. If you didn’t add a passphrase to your DSA key, you should be logged into SiteGround without having to supply a passphrase. Press Control-D to log out.

Now your git endpoint can be simplified for your git client (username and port are removed):

ssh://mXX.siteground.biz/home/sguser/public_html/git

But don’t clone it just yet!

How not to push, and what will happen

The normal Git push workflow (for me) would be to init a git repository on my local system, add an origin of bitbucket.org or github.com and push it there, then add remotes (such as WPEngine production and staging) and proceed to push to those remotes. Instead I added SiteGround as a remote named sg-remote.

Origin vs. Endpoint

They key difference between SiteGround and WPEngine is that SiteGround treats their git repository as an origin (where you can pull and push), where WPEngine is a --bare endpoint that you can only push to.

Since SiteGround is set up as an origin, if you just try to push there (without pulling or cloning from SiteGround first), you’ll likely get a warning like:

Updates were rejected because the remote contains work that you do not have locally.

Per git’s recommendation, you might then try to pull:

git pull sg-staging master

If your git repository was set up to not track WP core files, you’ll get a warning that:

error: The following untracked working tree files would be overwritten by merge:
index.php
license.txt
readme.html
wp-activate.php
wp-admin/about.php
...
Aborting

This is because the core WP files have been added to the SG-git repo, but not your local one. So then if your next move is:

git push sg-staging master --force

Several important files will be removed on your WP install at SiteGround: all of wp-admin, wp-config.php, and all other PHP files in the webroot folder. Needless to say, your WordPress instance will no longer function without some serious repair.

Git push to SiteGround (modified functional workflow)

Since SiteGround sets up the git repository as an origin, it is better to start your WP project with a git clone from SiteGround, but before doing that, I wanted to clean things up…

If you don’t want core WP files under version control, the easiest solution is to remove them from version control directly at SiteGround before cloning the repo.

Since we’ve already got SSH working, from your terminal you can:

ssh mXX.siteground.biz
cd /home/sguser/public_html/git
git rm --cached -r wp-admin/ wp-includes/ *.php *.txt *.html
git commit -a -m "Removed WP-Core files"

Again, replace the host (ssh line) and path (cd line) with the values from your git clone command supplied by SiteGround. The ones used here are examples. The git rm --cached command removes the core WP files from revision control, but leaves them on the filesystem, so your installation doesn’t go into a state of disrepair (like above).

Once that is done, you can clone!

git clone ssh://mXX.siteground.biz/home/sguser/public_html/git

SiteGround will be the origin, so let’s edit that (usually bitbucket.org or github.com is the true origin). This will rename it to sg-remote:

git remote rename origin sg-remote

Now when you want to push to SiteGround, just do:

git push sg-remote master

If you try to push a different branch to SiteGround, the branch will be transferred, but the code won’t be switched to that branch. To get around this you can overwrite SiteGround master by doing:

git push sg-remote my-branch:master

Hopefully this gives you some insight into how the SiteGround git deployments work, so you can use them effectively.

If you’re interesting in learning more about git deployments or how to set up your own git-push-to-deploy, I recommend starting with this article to familiarize yourself with a basic setup:

https://www.digitalocean.com/community/tutorials/how-to-set-up-automatic-deployment-with-git-with-a-vps

Continue Reading

justin

    More by justin

    Developing WordPress Locally – Part 2

    Posted on November 17, 2013

    In Part 1 of this series I shared the process I go through to set up a local WordPress workspace for developing client websites when we are starting from scratch. In this post I will show you how I set up a workspace for clients who already have an existing website.

    While I am explaining this as a process for working on a client’s website, this is also a great way to run a development version of your own website. It will allow you to try out plugins and themes using your real data so you can see exactly how it will work BEFORE you push it live.

    Since many of the tools and steps I am going to use are the same as they are in Part 1 of this post series, I may gloss over details that are covered more in-depth in the previous post.

    Tools

    As I said before, I am developing on a Mac. Many of the tools I use are Mac specific. If you are on a PC, the concepts will be the same, but you may need to find a comparable tool.

    Here’s the list of tools I’ll be using:

    • DesktopServer
    • Tower
    • Transmit
    • bitbucket.org
    • WP Migrate DB Pro
    • Uploads by Proxy

    Before you get started

    By now you should have already collected the FTP information and WordPress admin login credentials for the site you’re working on. If not, do that now. I’ll also mention that having a BitBucket account isn’t a requirement for what I’m going to show you here, but it is part of MY process, so I’m leaving it in, but you can skip that part if you’d like. OK, I think we’re set. Let’s do this!

    Aaaaand Go

    Just like I said in the previous post, I’m going to break up the process in to a number of ‘steps.’ Each time there’s a new step, that simply means we are changing applications. In my head, this makes the most sense for breaking up this post in to digestible segments.

    Step 1: Desktop Server

    First thing we’re going to do is set up a copy of WordPress to work on locally. In DesktopServer, start by choosing the ‘Create a new development environment’ radio button. On the next screen you will enter a site name and in the Blueprint dropdown choose the latest version of WordPress and click continue. After the install is complete, click Done and you’ll see the congratulations screen with a link to your new local WordPress install. Click the link to finish the WordPress install in the browser.
    Create Siteds-new-siteds-congrats

    Note: DesktopServer lets you create your own ‘Blueprints.’ These are folders that contain the default WordPress install and you can add your own default themes and plugins. As an example, I have the latest version of Genesis in the theme folder and I have a handful of plugins I use for development in the plugins folder. This is a nice time saver when setting up a dev environment.

    Step 1.5

    You may have noticed in my screenshot, my Desktop Server Blueprint is out of date. Because I installed an older version of WordPress, and some of my plugins are out of date, my next step is to log in to my new local WordPress install and update WordPress core and all plugins directly from the WordPress admin area. Just because we are working locally, there’s no need for us to jump through any crazy hoops to update WordPress. I love that about Desktop Server.

    Step 2: Transmit

    In Transmit, I create a new connection profile and fill in the details for my client’s website. I then connect to the server and I download everything from their wp-content/themes/ folder and wp-content/plugins/ folder. I store these in the matching folders inside our newly created website on our local machine.
    transmit-createtransmit-folders

    Note: If the site I am working on doesn’t have a huge amount of files in the uploads folder, I will go ahead and download that now as well. But, if it does have a large number of files, I will instead use the Uploads By Proxy plugin, which I will explain in a later step.

    Step 3: WP Migrate DB Pro

    If there is one plugin that saves me the most amount of time, it has to be WP Migrate DB Pro. We are going to use the plugin to mirror our live site on our local install.

    Start by installing the WP Migrate DB Pro plugin on both your live site and your local installation.

    On the live website, in the WordPress dashboard, go to Tools -> Migrate DB Pro. Click the Settings tab at the top. On the resulting screen click the “Accept pull requests allow this database to be exported and download” checkbox. Then, highlight and copy the information in the ‘Connection Info’ box.
    migrate-live

    On the local website, in the WordPress dashboard, go to Tools -> Migrate DB Pro. On the Migrate tab, click the ‘Pull’ radio button and paste in the connection info you copied a second ago. You do not need to click the ‘connect’ button. After a second you should see a screen that looks similar to this:
    migrate-local

    Click the ‘Migrate DB’ button at the bottom and the plugin will start pulling a copy of the live database and using it to replace your local database. It will also update all the website URL references and path references based on what it auto-detected. You can see that in the screenshot just above. When it’s done, you’ll see a confirmation message like this one:
    migrate-done

    47 seconds. Done and done.

    Important Note: Your local database and your live database are the same. This means that the username and password that you set up locally in Step 1 above will no longer work. You need to log in using a username/password that existed on the live website.

    At this point, we’re done touching the live website. All further steps in this process are done on your local WordPress installation.

    Step 4: Uploads by Proxy

    If you downloaded the /wp-content/uploads/ folder in step 2, you can skip ahead to Step 5.

    When a client has a large number of files in their uploads folder, rather than spending time waiting for them all to download and taking up space on my hard drive, the Uploads by Proxy plugin comes to the rescue. Install the plugin and activate it.

    Open Sublime Text 2 and open your wp-config.php file located in the root folder of your WordPress install. Add the following two lines to your wp-config file, just about where it suggests you stop editing.
    define(‘WP_SITEURL’, ‘http://ignitevegas.com’);
    define(‘UBP_SITEURL’, ‘http://ignitevegas.com’);
    Like this:
    sublime-ubp

    Now our local site is displaying images directly from the live site. Here’s a before and after:
    ubp-beforeubp-after

    OK, one final warning about Uploads by Proxy. If you are planning to do development on your local computer from a location where you won’t have an internet connection, then using Uploads by Proxy is a bad idea! Go back and download the uploads folder instead.

    Technically speaking, you are ready to start working on your site. However, before I get started I like to create a BitBucket repo and store a copy of the site files as they are now before I do any work. It’s always nice to have a rollback point in case something goes horribly horribly wrong. That being said…

    Step 5: Tower

    Before I create my local repo, I save a copy of this file in to the root folder of my local WordPress install and rename it to .gitignore (It has to be named exactly like that. See the explanation in the first post if needed.

    From the Tower dashboard, click the “Create Local Repository” link. In the pop-up, click Browse to select the root folder for your local WordPress install. Give it a proper title and click OK.
    tower-localrepo

    Once the repo is created, double click it and you should see something similar to this:
    tower-new-repo

    I then do an initial commit of the .gitignore file and the wp-content folder. I do this by clicking the ‘Stage all’ button, clicking ‘commit’ and in the pop-up I type in ‘initial install’
    tower-initial-commit

    Step 6: BitBucket

    In my bitbucket.org account, I create a new BitBucket repo. Like this:
    bitbucket-create

    Once the repo is created I select the Clone button and switch the second dropdown to SSH. In the screenshot below you’ll see that in the highlighted area it says ‘git clone git@bitbucket…’. We don’t actually need the ‘git clone’ portion. We want to copy everything after that. In this example, that’s going to look like this: [email protected]:9seeds/ignite-vegas.git Once we have that copied to the clipboard, we’re done with bitbucket.
    bb-clone

    Step 7: Tower

    Now I’m going to add BitBucket as a ‘remote’ so that I can store a copy of the code in a central location for myself and my team to access later on. I do this by right-clicking on ‘Remotes’ and in the pop-up, I fill type in ‘BitBucket’ as the name of the remote and then paste in the info I copied in the previous step. I select Private Key from the dropdown and click OK.
    tower-remote

    The last step is to drag the ‘master’ branch on to the ‘BitBucket’ Remote. This will do an initial push of our local repository up to BitBucket. In the pop-up window, make sure to have the ‘Track this new remote branch’ checked and then hit OK.
    tower-track

    Alright, NOW you are really done. Now it’s time to open up your editor and get to work.

    Sign up for the 9seeds.com newsletter to make sure you catch next week’s final post in the series where I’ll cover how we take the work we’ve done locally and push it to the live server.

    Want More?

    – Read Part 1 of this series
    – Read Part 3 of this series
    – Sign up for our newsletter

    Continue Reading

    john

      More by john

      Want more free plugins? You might have to pay for them

      Posted on June 4, 2013

      Normally I do a lot of contemplation while riding my bike. This week, it happened while mowing the lawn. I was thinking about Chris Lema’s post about commercial WordPress plugins being too inexpensive.

      Strangely enough, it got me thinking not about commercial plugins, but about free plugins. Everyone wants free plugins. WordPress is free, BuddyPress is free. There are several great free plugins out there that will make WordPress do strange and wonderful things.

      Continue Reading

      justin

        More by justin

        Footer

        Get in Touch

        • New Project Inquiry
        • Product Support and General Inquiry
        • Store Purchase Terms and Conditions
        • Store FAQ
        • Cookie Policy
        • Privacy Policy

        Our Services

        • Custom WP Development
        • Theme Store
        • Plugin Store

        WordPress Plugins for Sale

        • Time Tracker
        • Authorize.net SIM Gateway

        WordPress Plugins for Free

        • Simple Calendar
        • WP Chargify
        • Facebook
        • Twitter
        • LinkedIn
        • WordPress
        • GitHub

        Copyright 2025 | 9seeds, LLC

        Like nearly all websites this one uses cookies too. Like most users we think consent banners like these are a dumb solution, but it's what we've got until new laws are passed. We use cookies on our website for remembering your preferences, for example if you're logged in or what is in your cart. We also use 3rd party cookies for analytics so we know what pages on the site are most popular. By clicking “Accept”, you consent to the use of ALL the cookies.
        Do not sell my personal information.
        Cookie SettingsAccept
        Manage consent

        Privacy Overview

        This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience and may even preclude you being able to login to the website.
        Necessary
        Always Enabled
        Necessary cookies are absolutely essential for the website to function properly. These cookies ensure basic functionalities and security features of the website, anonymously.
        CookieDurationDescription
        __stripe_mid1 yearThis cookie is set by Stripe payment gateway. This cookie is used to enable payment on the website without storing any patment information on a server.
        __stripe_sid30 minutesThis cookie is set by Stripe payment gateway. This cookie is used to enable payment on the website without storing any patment information on a server.
        cookielawinfo-checkbox-advertisement1 yearSet by the GDPR Cookie Consent plugin, this cookie is used to record the user consent for the cookies in the "Advertisement" category .
        cookielawinfo-checkbox-analytics1 yearSet by the GDPR Cookie Consent plugin, this cookie is used to record the user consent for the cookies in the "Analytics" category .
        cookielawinfo-checkbox-necessary1 yearSet by the GDPR Cookie Consent plugin, this cookie is used to record the user consent for the cookies in the "Necessary" category .
        cookielawinfo-checkbox-others1 yearSet by the GDPR Cookie Consent plugin, this cookie is used to store the user consent for cookies in the category "Others".
        cookielawinfo-checkbox-performance1 yearSet by the GDPR Cookie Consent plugin, this cookie is used to store the user consent for cookies in the category "Performance".
        Functional
        Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
        Performance
        Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.
        Analytics
        Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
        CookieDurationDescription
        _ga2 yearsThe _ga cookie, installed by Google Analytics, calculates visitor, session and campaign data and also keeps track of site usage for the site's analytics report. The cookie stores information anonymously and assigns a randomly generated number to recognize unique visitors.
        _gid1 dayInstalled by Google Analytics, _gid cookie stores information on how visitors use a website, while also creating an analytics report of the website's performance. Some of the data that are collected include the number of visitors, their source, and the pages they visit anonymously.
        CONSENT2 yearsYouTube sets this cookie via embedded youtube-videos and registers anonymous statistical data.
        Advertisement
        Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.
        CookieDurationDescription
        VISITOR_INFO1_LIVE5 months 27 daysA cookie set by YouTube to measure bandwidth that determines whether the user gets the new or old player interface.
        YSCsessionYSC cookie is set by Youtube and is used to track the views of embedded videos on Youtube pages.
        yt-remote-connected-devicesneverYouTube sets this cookie to store the video preferences of the user using embedded YouTube video.
        yt-remote-device-idneverYouTube sets this cookie to store the video preferences of the user using embedded YouTube video.
        Others
        Other uncategorized cookies are those that are being analyzed and have not been classified into a category as yet.
        CookieDurationDescription
        cookielawinfo-checkbox-functional1 yearThe cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional".
        SAVE & ACCEPT
        Powered by CookieYes Logo