Easy Automatic Code Deployment With Git
Tags: git, tutorial, productivity
Published: 2021-11-08 17:09:13

# Introduction

I will show you how to deploy code to a live server easily with Git.

Let's say you have already [deployed your project](https://dev.to/brandonwallace/deploy-flask-the-easy-way-with-gunicorn-and-nginx-jgc) to a live server. A few days later you receive valuable feedback on your project from another developer. You decide to make some improvements to the project. You work in your local Git repository to make the changes. You test everything to make sure it is working the way you intended it to work. Then you commit the changes in your code to your local Git repository. Then you push those changes to Github.

How do you go about getting those improvements to the live server? Would you log into the server and meticulously edit the file manually?

There is an easy way to deploy code to a live server - use Git. All you need it is the ability to SSH to the server.

Here is the syntax for the git push command:

`$ git push <repository> <branch_name>`

Example:

```bash
$ git push origin main
```

The `origin` is first repository that is set up and usually represents the repository connected to the Github website. 

To get code to a live server, I will create a second repository on the live server to push code to. I will call the second repository "prod" to represent the repository on the live production server. 

After pushing code to the "origin" repository I will be able to push to "prod" any code ready for production. 

When I am ready to push code to the production server I run this command.

```bash
$ git push prod main
```

## On the server

We need two directories on the server, one for the application which holds the production code, and one directory for the Git bare repository.

Directory for production code:

`/var/www/my_project/`

Git bare repository:

`/var/repos/my_project.git/`


### Set up a repository on the server.

The first step to set this up is to create a bare repository on the web server where you will run the application.

SSH to your server. My server has the user `brandon` and the IP address `123.45.67.89`. So I use this command.

```bash
$ ssh brandon@123.45.67.89
```

Create the directory as a Git bare repository with a `.git` at the end of the name.

```
$ sudo mkdir -p -v /var/repos/my_project.git/
```

Set the permissions on the directory.

```
$ sudo chown $USER:$USER /var/repos/my_project.git/
```

Move into the `my_project.git/` directory.

```
cd /var/repos/my_project.git/
```

Run the git init --bare command inside the /var/repos/my_project.git/ directory.

```
$ git init --bare
```

The directory structure should look like this.

```
$ tree --dirsfirst -F
.
├── branches/
├── hooks/
│   ├── applypatch-msg.sample*
│   ├── commit-msg.sample*
│   ├── fsmonitor-watchman.sample*
│   ├── post-update.sample*
│   ├── pre-applypatch.sample*
│   ├── pre-commit.sample*
│   ├── pre-merge-commit.sample*
│   ├── prepare-commit-msg.sample*
│   ├── pre-push.sample*
│   ├── pre-rebase.sample*
│   ├── pre-receive.sample*
│   ├── push-to-checkout.sample*
│   └── update.sample*
├── info/
│   └── exclude
├── objects/
│   ├── info/
│   └── pack/
├── refs/
│   ├── heads/
│   └── tags/
├── config
├── description
└── HEAD
```

### Creating a hook to perform an action.

A hook will allow you to run a script when a particular action occurs. There are hooks that run on the client and hooks that run on the server. I will set up the server-side hook `post-receive` that will run once a git push has finished executing. 

Create a file called `post-receive` in the hooks directory.

```
$ touch hooks/post-receive
```

Use any text editor to edit the post-receive file.

```
$ vim hooks/post-receive
```

Add the following content, change the paths to reflect your set up.

```
#!/bin/sh

git --work-tree=/var/www/my_project/ --git-dir=/var/repos/my_project.git checkout -f main
```

The post-receive script is not executable.

```
$ ls -lF hooks/post-receive 

-rw------- 1 brandon brandon 0 Nov  2 21:19 hooks/post-receive
```

Make the script executable by running the `chmod` command.

```
$ chmod +x hooks/post-receive

$ ls -lF hooks/post-receive 

-rwx------ 1 brandon brandon 0 Nov  2 21:19 hooks/post-receive*
```

# On my laptop

### Connect your local repository to the server repository.

On the client machine where my local repository is located I will connect that repository to the one I created on the live server.

Create a local repository with the same name as the directory on the server minus the `.git` extension.

```
$ mkdir my_project/
```

Move into the directory.

```
$ cd my_project/
```

Set up git in the project directory with a few basic files.

```
$ git init

$ touch .gitignore readme.md LICENSE
```

Add content to the readme.md file.

```
$ echo '# My Auto Deploy Project' >> readme.md
```

With any text editor add a simple index.html file to the project.

```
$ vim index.html
```

Add the following content to the index.html file.

```
<!DOCTYPE html>
<html lang="en">

  <head>
  
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <meta name="description" content="My auto deploy project.">
    <link rel="stylesheet" href="style.css">
    <title>Hello World!</title>
  
  </head>
  
  <body>
  
    <h1>Hello World!</h1>
  
  </body>

</html>
```

Add all the files to Git and commit the changes.

```
$ git add --all

$ git commit -m "First commit"
```
Create a new repository on Github without the readme.md, .gitignore, or LICENSE. We have already created those files for the Github repository. Name the Github repository the same as the local repository. My local repository is called `my_project` so I use the same name to create the Github repository. See screenshot below.

![create-gh-repo.png](https://i.postimg.cc/TwFkrsDr/create-gh-repo.png)

Connect the local repository to Github. Make sure the branch is called `main`.

```
$ git remote add origin git@github.com:brandon-wallace/my_project.git

$ git branch -M main
```

Set `origin` as the default repository to push to.

```
$ git push -u origin main

Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 550 bytes | 550.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:brandon-wallace/my_project.git
 * [new branch]      main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.

```
I have successfully connected the local repository to Github. Now I will connect the local repository to the live production server. My server has the IP address `123.45.67.89` and SSH on port `22` so I run this command with the full path to the `my_project.git` directory.

Syntax:

`$ git remote add <remote_repository> ssh://<username>@<server_ip>:<port>/path/to/<project>.git`

This is the command I run.

```
$ git remote add prod ssh://brandon@123.45.67.89:22/var/repos/my_project.git
```
When I want to push code to the production server. I run this command.

```
$ git push prod main

Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 550 bytes | 550.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Switched to branch 'main'
To 123.45.67.89:/var/www/my_project_repo/my_project.git
 * [new branch]      main -> main
```

View the remotes. This shows that there are two remote repositories available, `prod` and `origin`.

```
$ git remote -v

prod	ssh://brandon@123.45.67.89:22/var/repos/my_project.git (fetch)
prod	ssh://brandon@123.45.67.89:22/var/repos/my_project.git (push)
origin	https://github.com/brandon-wallace/my_project.git (fetch)
origin	https://github.com/brandon-wallace/my_project.git (push)
```

I will make some changes to the project and push those to the production server.

```
$ touch style.css
```
Add some content to the CSS file with any text editor.

```
$ vim sytle.css

# Example content

html {
	font-size: 100%;
}

body {
    background: #FFFFFF;
    font-family: sans-serif;
    font-weight: 400;
    line-height: 1.75;
    color: #000000;
}

h1 {
    margin-top: 0;
    font-size: 3.052rem;
}
```

Add the new CSS file. Commit the changes to the repository.

```
$ git add style.css

$ git commit -m "Add CSS file"

# Output

[main 8881680] Add CSS file
 1 files changed, 27 insertions(+), 3 deletions(-)
 create mode 100644 style.css
```

Right now, on the server I can see four files in `my_project/`.

```
$ /var/www/my_project/ $ ls -l
total 12
-rw-r--r-- 1 brandon brandon  319 Nov  7 10:25 index.html
-rw-r--r-- 1 brandon brandon    0 Nov  7 10:25 LICENSE
drwxr-xr-x 8 brandon brandon 4096 Nov  7 10:25 my_project.git
-rw-r--r-- 1 brandon brandon   25 Nov  7 10:25 readme.md

```

Push the changes to the production server.

```
$ git push prod main

Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 4 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 623 bytes | 623.00 KiB/s, done.
Total 4 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Already on 'main'
To 123.45.67.89:/var/repos/my_project.git
   083f700..8881680  main -> main
```

Now on the server I can see the `style.css` I just pushed to the `prod` repository running on the live server.

```
/var/www/my_project $ ls -l
total 16
-rw-r--r-- 1 brandon brandon  362 Nov  7 10:56 index.html
-rw-r--r-- 1 brandon brandon    0 Nov  7 10:25 LICENSE
drwxr-xr-x 8 brandon brandon 4096 Nov  7 10:56 my_project.git
-rw-r--r-- 1 brandon brandon   25 Nov  7 10:25 readme.md
-rw-r--r-- 1 brandon brandon  365 Nov  7 10:56 style.css
```

## Troubleshooting

First, check carefully for spelling errors is highly recommended.

If you get `-bash: git: command not found` error install `git`.

```
$ sudo apt update

$ sudo apt install git
```

You get the error: 
```
ssh: Could not resolve hostname github.com: Temporary failure in name resolution
fatal: Could not read from remote repository...
```

You need to set up SSH keys on Github.

# Conclusion

I hope you learn something new by reading this article. Using Git you can easily push changes to a project to a live production server. 

![Github](https://github.com/brandon-wallace)![DEV.to](https://dev.to/brandonwallace)

Feel free to leave feedback, comments, or suggestions.