SFTP, SCP, Rsync, the good old FTP – there are many ways to deliver an app. The choice depends on many factors, such as working speed, infrastructure limitations (some servers allow only FTP upload), or developer preferences.

A couple weeks ago we made an analysis on what our clients use for application upload. The clear winner was the FTP protocol. Right after it there were SFTP and Rsync. However, in this post we'd like to talk about the fourth contender that's missed the podium by scratch: Git.

The strong position of FTP most probably results from its popularity among WordPress and PHP developers and the fact that many servers don't allow any other upload option. However, the protocol has one big flaw: front-end apps contain a lot of files and uploading them can take a long time.

Buddy uploads only those files that were changed, which significantly shortens the upload time.

Git deployment

Every developer knows Git. If you want to pull the latest version of the repo, you run git pull. If you want to share changes with others, you run git push. And since only changesets are uploaded, these operations are very fast. However, many people don't know that they can deploy apps in the same way. In this article we'll describe how to configure a server to release an application with git push/pull.

Before we get down to bussines, though, let's remember one important rule:

Never keep dependencies and compiled artifacts in repo!

If you'd like to learn why (and you should), we've covered it in detail in this article.


Git pull

In this case we have a clone of our repo on the server where the app is run. When we want to release a new version we execute there git pull and in that way we have the latest version of the app.

Setup

Frist, install SSH and Git on the server:

$ sudo apt-get install -y openssh-server git

Now, create a folder from which we'll serve our app and initiate git repo in it:

$ mkdir ~/www/app.com
$ cd  ~/www/app.com
$ git init

The last thing is adding the remote to our repo and pulling the application:

git remote add origin URL
git pull master

The best practice is to create a new user on the server and grant him/her access to the Git repo (GitHub/Bitbucket/GitLab, etc.). Here's a good tutorial how to do it.

If our application requires to be built (fetch dependencies, compile assets, generate artifacts, etc.), we'll execute the build commands manually on the server (npm, compser, yarn install, gulp grunt webpack, etc.).

Release

Every time we want to release our app, we connect to the server and execute git pull and the build commands there.

Rollback is very easy, too: all you need to do is checkout the revision to which you want to return, and build the app again.


Git push

In the previous use-case, we connected to the server first and executed commands later. Now we'll learn how to make a release with locally executed git push.

Setup

Just like with the 'git pull' use-case, we need a server with SSH and Git installed:

$ sudo apt-get install -y openssh-server git

Create a folder from which we'll serve our app, and initiate git repo in there:

$ mkdir ~/www/app.com
$ cd  ~/www/app.com
$ git init

Now we need to configure Git to allow for ref update to the currently checked out branch, and set workfree to the directory with the repo.

$ git config receive.denycurrentbranch ignore
$ git config core.worktree ~/www/app.com

The last thing is setting a post-receive hook. It'll checkout the new version of the repo and build the app if needed.

Go to edit mode

$ nano .git/hooks/post-receive

and set the scripts:

#!/bin/sh
# checkout HEAD
git checkout -f
# fetch dependencies and build
npm install
gulp 

Finally, we set the permissions to the file:

$ chmod +x .git/hooks/post-receive

Done! The rest we'll do locally.

Release

We'll deploy the new version of the app right from our repo. All we need to do is add a proper remote to it (let's call it 'Production'):

$ cd ~/repos/myrepo
$ git remote add production ssh://user@ip/home/user/www/app.com

The authorization is performed with SSH. In our case it's the same user that we used to perform the setup.

To release the application, just execute:

$ git push production master

Pros and Cons of Git deployment

The major pro is definitely the release time of every next version of the application: it's fast because only changesets are pulled.

On the other hand, the main disadvantage of deploying with Git is that the app need to be built on the server. This extends the downtime, because we have to wait until the dependencies are pulled and the build performed. Moreover, in both cases we need to remember to test the app before the deployment.

We have described how to create mechanisms that will shorten the application downtime here.