• 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

tutorial

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

    Moving forums from SimplePress to BBPress

    Posted on February 4, 2013

    I was recently asked by a member of our local WordPress meetup group which forum software I would suggest using. I mentioned that I had been using SimplePress for a while, but wasn’t in love with it. I had used BBPress quite a while ago, before it got the major revamp and if I had to choose which to use for a new site, I would go with BBPress. Then, with a stroke of great timing, the BBPress 2.3 beta was released the following day. Since it was fresh in my mind, I installed the beta to test it out. In short, BBPress has come a LONG way in the past year. So much so that we decided it was time to move our support forums off of SimplePress. That process would prove to be tricky.

    To follow are the steps I took to convert our forums from SimplePress version 4.4.0 to BBPress version 2.3

    Step 0

    Backup All The Things

    Seriously. Just do it.

    I went one step further than just backing everything up. Instead, I exported the database and set up a separate WordPress install just to run the conversion. This way, if everything broke I could simple delete it and start again. And now the actual conversion process.

    Step 1: Upgrade SimplePress

    When figuring out what it would take to do the conversion, I found that BBPress could convert SimplePress version 5 forums right from the tools menu. So in order to do the conversion, I first needed to upgrade SimplePress. Unfortunately, their upgrade only works with version 4.5.x. After reading this page, I took these steps:

    – Deactivate the SimplePress plugin (Do Not uninstall it, just deactivate it)
    – Remove the /plugins/simple-forum/ folder from your server
    – Download the latest version of SimplePress
    – Upload simple-press folder to /plugins/simple-press/ on your server
    – Activate the plugin

    Once the plugin is activated, you’ll have the “Forums” item added back to your menu which will link you to an upgrade process. Start the upgrade process and let it run. For our small forum this process took 3-4 minutes. I’m assuming for a larger forum, this process could take a bit longer. Be patient.

    After I ran the update, poking around the forums admin area, everything looked fine. I then checked the actual forums and found this message:

    SP error

    I was concerned that I had lost all my data, but the forum stats displaying below gave me some comfort.

    Forum Stats

     

    Step 2: Install BBPress

    Not wanting BBPress and SimplePress to colide, I started by deactivating SimplePress. I then uploaded the BBPress 2.3 beta to /plugins/bbpress/ and activated it from the plugins menu.

    Yeah, that part was pretty simple.

    Step 3: Import SimplePress forums

    Just a quick note. At the time of this writing BBPress 2.3 beta 2 has a bug related to importing of data. I posted a ticket about it in Trac and I’m sure it will be fixed soon. To get around the bug, I ran a search and replace on the database to remove any instance of   as it causes the post to be truncated upon import.

    Start by going to Tools -> Forums in the WordPress admin area, then click the Import Forums tab at the top. From the dropdown select SimplePress 5 and then fill in the database information. Just under that you’ll see a few options. The most important of which is the Convert Users option.

    The first time I ran the import, I was installing BBPress on the same WordPress installation that SimplePress had previously been installed on. This meant that all my user accounts already existed and their posts were all connected to them. I clicked the convert users tab prior to running the import, and all the posts, once converted, were once again attached to their rightful owners as part of BBPress.

    I then decided that I wanted to move my forum to a different WordPress install on a different domain. When doing so, I accidentally forgot to click the Convert Users checkbox. The results were less than optimal. All of the posts DID come over to the new installation, but they were all attached to a single user account. Oops.

    I can’t think of a reason (although, I’m sure there is one or this wouldn’t be an option) why you would ever want to NOT click the Convert Users checkbox. So before you click Start, make sure it’s checked.

    Step 4: Repair Forums

    After running the conversion in step 3, I was reviewing the forums and noticed that all the data appeared to be in place and the posts were all attached to the proper people, but, all of the counts were off. Anywhere where it said how many posts or replies were on a post or topic was all displaying zero. Back to the admin area we go. This time to Tools -> Forums and click the Repair Forums tab where you will find the following options:

    Repair Forums

    Taking the advice along the top, I clicked the first item in the list and then clicked Repair Items. It took a matter of seconds to complete. I then went through each item on the list, one at a time, and checked the box and ran the repair. When I was done I went back to the forums to find that all the counts had been updated and my forums were working perfectly.

    Once you know all the pieces, the process isn’t actually all that difficult. But hopefully I just saved you some trial and error time.

    Done Done. (as Chris Lema would say)

     

    Continue Reading

    john

      More by john

      Converting Blogspot / Blogger to hosted WordPress

      Posted on April 16, 2012

      First Try

      Migrating your Blogspot or Blogger weblog to a hosted WordPress installation should be easy.  But you may run into some problems along the way, so here are some quick ways to make it less painful.

      When I first attempted this, I used the Blogger Importer plugin found in the “Tools” → “Import” menu of a new WordPress installation.  It went OK.  The importer pulled in all of the posts and the comments, but there seemed to be some extra markup that made it’s way into the posts.  All of the post titles now started with “>”:

      >Why Hello There!

      Also, while images in the content seemed to be fine, none of the media was actually imported into WordPress, they were still being hosted on blogspot.com.

      Resetting the WordPress installation to start over

      So now WordPress has a bunch of content that I want to delete so that I can start over and hopefully get it right the next time.  For this I used WordPress Reset.  I was able to use it to remove the (bad) imported content and reset it back to a new installation.  It’s multi-site friendly and only restored the one site and left all the content from the parent and sibling sites alone – although I can’t vouch for what it would do if you ran it on the parent site of a network installation.

      A 2-Step Approach

      Now that I was back to square one it was time for a different approach.  After some reasearch, someone on the WordPress Forums mentioned using WordPress.com to do the Blogger import, then exporting from WordPress.com as a native WordPress export file (WXR / XML), and import that file into your new WordPress installation.

      Importing Blogspot / Blogger to WordPress.com

      So over at WordPress.com, everything is like a normal WordPress installation, except they have turned it up to 11.  They have powerful servers, and a dedicated staff that make amazing additions to the most popular free plugins – one of which is the Blogger import.  On WordPress.com you have an additional option to import a Blogger export file:

      Rather than authorizing the plugin to get everything from the site, we’ll export it to a file. Log into your Blogger account. When you’re logged in and viewing your blog there’s a “Design” link in the upper right menu bar, click that. Once you’re at the Blogger administration page click the “Settings” menu, and then “Other.” You will have an option under “Blog Tools” to “Export blog”:

      Take that file and import it into a new WordPress.com site. You’ll want to make sure that this blog is public (but not necessarily indexed by search engines) as our hosted WordPress installation will need to be able to pull media files from it, but we don’t want it to wind up on Google, as it’s only temporary. It might take a while to fully complete, but WordPress.com should bring in all your Posts, Comments, and Media just fine. Once you’re sure that it’s done, export the WordPress.com site through the “Tools” → “Export” menu, selecting “All Content.”

      Importing WordPress.com’s export into a hosted WordPress site

      Before we begin importing the content from WordPress.com, two things should be changed in the WordPress Importer plugin‘s wordpress-importer.php file, which can be done through the plugin editor.

      Just so we know when the importer runs into issues, change IMPORT_DEBUG to true:

      /** Display verbose errors */
      define( 'IMPORT_DEBUG', true );

      Then to make sure we get everything, find the line that starts with:

      $post_exists = post_exists( $post['post_title'], ...

      This was on line 539 for me.  Comment it out using slashes:

      //$post_exists = post_exists( $post['post_title'], ...

      Then just below that line add:

      $post_exists = false;

      I did this because when WordPress.com imported images from Blogger, it gave them the same name as the post title, So if a post was called “Why Hello There!” and it had 5 pictures in it, all 5 pictures also had the title “Why Hello There!” This was preventing the importer from getting everything. Plus I already reset the installation, so there’s no content to duplicate or overwrite anyway. And I reasonably trust that I want to retrieve everything contained in the WordPress.com export file.

      Run your import and everything should go smoothly. After you’ve verified you have everything in your new hosted WordPress installation, you can delete your WordPress.com site or make it private. You may also want to undo the WordPress Importer changes for future imports.

      Continue Reading

      justin

        More by justin

        Drupal to WordPress migration

        Posted on October 2, 2010

        Updated: 8/19/2013 – 9seeds does not offer Drupal to WordPress conversion as a stand-alone service. If you need to convert from one CMS to another, we suggest you check out https://9seeds.com/cms2cms

        A client came to us this week with a problem; he had a Drupal site with over 1000 articles that he wanted to convert to WordPress. So we headed to Google for some help. There are several tutorials out there on how to migrate Drupal content to a WordPress site, but many of them are really outdated. After kicking the tires on a few, this post by Mike Smullin seemed to be the best jumping off point.

        Mike is right up front in his instructions with the fact that you’ll need to do a bit of tweaking to his set of instructions to get it to work for your setup. After a few failed attempts, we came up with an updated set of instructions. We’ve included the updated version along with notes about changes made.

        These instructions are a set of SQL statements. It assumes you have a database named WordPress using ‘wp_’ as the prefix and another database named Drupal.

        This should go without saying, but I’ll say it anyway; do not move forward without backing up your databases FIRST!

        Clear all existing WordPress content

        TRUNCATE TABLE wordpress.wp_comments;
        TRUNCATE TABLE wordpress.wp_links;
        TRUNCATE TABLE wordpress.wp_postmeta;
        TRUNCATE TABLE wordpress.wp_posts;
        TRUNCATE TABLE wordpress.wp_term_relationships;
        TRUNCATE TABLE wordpress.wp_term_taxonomy;
        TRUNCATE TABLE wordpress.wp_terms;
        

        Create Categories

        INSERT INTO wordpress.wp_terms (term_id, `name`, slug, term_group)
        SELECT
         d.tid, d.name, REPLACE(LOWER(d.name), ' ', '_'), 0
        FROM drupal.term_data d
        INNER JOIN drupal.term_hierarchy h
         USING(tid);
        

        Add Taxonomies

        INSERT INTO wordpress.wp_term_taxonomy (term_id, taxonomy, description, parent)
        SELECT
         d.tid `term_id`,
         'category' `taxonomy`,
         d.description `description`,
         h.parent `parent`
        FROM drupal.term_data d
        INNER JOIN drupal.term_hierarchy h
         USING(tid);
        

        Import posts/pages
        We added ‘article’ to the array on the last line to solve an issue with the way Drupal had categorized the posts.

        INSERT INTO wordpress.wp_posts (id, post_date, post_content, post_title, post_excerpt, post_name, post_modified, post_type, `post_status`)
        SELECT DISTINCT
         n.nid `id`,
         FROM_UNIXTIME(n.created) `post_date`,
         r.body `post_content`,
         n.title `post_title`,
         r.teaser `post_excerpt`,
         IF(SUBSTR(a.dst, 11, 1) = '/', SUBSTR(a.dst, 12), a.dst) `post_name`,
         FROM_UNIXTIME(n.changed) `post_modified`,
         n.type `post_type`,
         IF(n.status = 1, 'publish', 'private') `post_status`
        FROM drupal.node n
        INNER JOIN drupal.node_revisions r
         USING(vid)
        LEFT OUTER JOIN drupal.url_alias a
         ON a.src = CONCAT('node/', n.nid)
        WHERE n.type IN ('post', 'page', 'article');
        

        Turn articles in to posts
        This will turn the ‘articles’ from the previous step in to ‘posts’ in WordPress.

        update wordpress.wp_posts set post_type='post' where post_type='article';
        

        Add post to category relationships

        INSERT INTO wordpress.wp_term_relationships (object_id, term_taxonomy_id)
        SELECT nid, tid FROM drupal.term_node;
        

        Update category count

        UPDATE wordpress.wp_term_taxonomy tt
        SET `count` = (
         SELECT COUNT(tr.object_id)
         FROM wordpress.wp_term_relationships tr
         WHERE tr.term_taxonomy_id = tt.term_taxonomy_id);
        

        Import comments

        INSERT INTO wordpress.wp_comments (comment_post_ID, comment_date, comment_content, comment_parent, comment_author, comment_author_email, comment_author_url, comment_approved)
        SELECT nid, FROM_UNIXTIME(timestamp), comment, thread, name, mail, homepage, status FROM drupal.comments;
        

        Update comment counts
        After fighting with the original syntax, I added the ‘use wordpress’ step to get around it.

        use wordpress;
        UPDATE `wp_posts` SET `comment_count` = (SELECT COUNT(`comment_post_id`) FROM `wp_comments` WHERE `wp_posts`.`id` = `wp_comments`.`comment_post_id`);
        

        Fix breaks in post content

        UPDATE wordpress.wp_posts SET post_content = REPLACE(post_content, '', '');
        

        Fix images in post content

        UPDATE wordpress.wp_posts SET post_content = REPLACE(post_content, '"/files/', '"/wp-content/uploads/');
        

        If your posts have any images you’ll need to move them from your ./files directory to the ./wp-content/uploads directory. The final step above should take care of fixing any image calls in your pages and posts, but you still may need to manually update them if you are having issues.

        Download a copy/paste friendly version of the Drupal to WordPress instructions here.

        if you have any questions, leave us a comment below.

        Continue Reading

        john

          More by john

          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