« What Type of Web Hosting is Right for You?GeekStorage Profile: Jeff Criswell, Account Manager »

'Git' Your Website Under Control!

'Git' Your Website Under Control!
August 8, 2012 at 9:33 AM

If you are reading this, you probably have a website. Maybe even a website on git-enabled shared hosting. Maybe you already know about git, or maybe not. Regardless, I would like to shed some light on how you can use the power of git  (or in this case, the simplicity of git) to 'git' your website under control! If you have ever fiddled with an FTP client, a text editor or an IDE for hours on end, just to squeeze a step or two out of your routine site updates or version deployments, you will soon have a friend in git.

With a few git commands under your belt, it is easy to go from FTP to a version control-enabled website deployment scheme. Click past the break to continue reading.

GeekStorage is proud to offer git website hosting.

Git

Git's primary purpose is to offer a means to maintain version control in your development projects. It allows you to do a lot of things any other "Version Control System" (VCS) would offer, but the shining light of git is just how darn simple it is. At its core, git is in charge of keeping track of changes that are made to files under its management. Let's take a quick look at how this basic functionality works.

A Git Crash Course

If you aren't familiar with SSH, check out our article on getting Up And Running With SSH. SSH is required to use git.

To tell git that it needs to manage files, we create a "repository" in our development directory. In this case, let's create a test directory and initialize our git repository. Working via SSH we issue the following commands to get started:

> mkdir git-test
> cd git-test
> git init
Initialized empty Git repository in /home/me/git-test/.git/

Right away, we see that our git repository has been initialized, but it's empty! Throw in a few files so we can see how git tracks our data.

> touch test test2 test3 test4
> git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       test
#       test2
#       test3
#       test4
nothing added to commit but untracked files present (use "git add" to track)

We can see that git is already tracking our changes. We have four untracked test files that are not yet tracked, and we have our branch indicator at the top. Think of a branch as a tree branch, but in the case of the "master" branch, think of it more like the trunk of the tree. We will eventually want to branch our project as a way of testing different implementations, changes or rewrites. But, first we'll start working on our initial commit. We'll add our files to the current commit (or update, save, whatever you prefer to think of it as) :

> git add touch test test2 test3 test4

Or, to add all of our current working directory files to git:

> git add .

I would like to mention that so far this is somewhat misleading. It sounds like we're "adding files to git", and in this case we really are, since it is the first commit. However, after the first commit, using the "git add" command really means "add these files to the current commit operation," providing a very powerful way of managing your updates and commits. Our `git status` should be tracking our files now.

> git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file:   test
#       new file:   test2
#       new file:   test3
#       new file:   test4
#

Great, now time to commit these files to the master branch! But first, let's tell git who we are. This is generally a one-time step for all of your git repositories (under the same shell account).

> git config --global user.email "[email protected]"
> git config --global user.name "Matt Eli" 

Ok, now time for the initial commit.

> git commit -m "My initial commit"
[master (root-commit) e63fb47] My initial commit
 0 files changed
 create mode 100644 test
 create mode 100644 test2
 create mode 100644 test3
 create mode 100644 test4

Our repository has its first commit, now let's change something and see what happens.

> echo "Test change" > test
> git diff
diff --git a/test b/test
index e69de29..693773e 100644
--- a/test
+++ b/test
@@ -0,0 +1 @@
+Test change 

Now our changes are being tracked within the files themselves. We created a new line in the "test" file with the text "Test change", clearly explained by the `git diff` command. Our status will show us that we have not added our "test" file to our commit. Let's commit our new change.

> git add test
> git commit -m "Updated 'test' with text" 
[master 401ae45] Updated 'test' with text
 1 file changed, 1 insertion(+) 

Great, the change has been reflected to our master repository, and every time we pull information from our master branch, we'll have text in our test file! Exciting! (Maybe not yet, but soon!) Let's find out what git knows about what we've done.

> git log
commit 401ae453203cd0926bb347b01b7c9e31185cef9c
Author: Matthew Eli <[email protected]>
Date:   Tue Aug 7 19:34:06 2012 -0500
 
    Updated 'test' with text
 
commit e63fb475f628fa824c2bc0f6c3433e7a84594da7
Author: Matthew Eli <[email protected]>
Date:   Tue Aug 7 19:29:02 2012 -0500
 
    My initial commit

Excellent, now we have a full history of all the changes made to our git repository. At this point, we can see what exact changes were made between commits, using the huge commit identifiers from `git log` like so:

> git diff e63fb475f628fa824c2bc0f6c3433e7a84594da7 401ae453203cd0926bb347b01b7c9e31185cef9c
diff --git a/test b/test
index e69de29..693773e 100644
--- a/test
+++ b/test
@@ -0,0 +1 @@
+Test change 

A record of all changes we have ever made can now be tracked by git. The most powerful "undo" and "redo" tool you could possibly imagine, right here, right now. Take our latest commit (401ae453203cd0926bb347b01b7c9e31185cef9c in our case) and wipe out that change! I hate text in this file!

> git revert -n 401ae453203cd0926bb347b01b7c9e31185cef9c
> git reset
> git add test
> git commit -m "I really dropped the ball this time, go away text" 

You can even revert commits that were reverts themselves, but it's time to get started with some real practical solutions for managing our website.

Git As A Tool For Webmasters

We like to think that FTP or even SCP are the only options for managing our website files, especially on shared hosting where there really aren't many options. The typical development process may involve downloading your site files, modifying them locally with your favorite text editor or WYSIWYG editor, and finally upload the changed files individually back to the website. Or, you might be better off with an FTP or SCP protocol built in to your editor, simplifying the process a bit. If you are working with a dev and production environment, you suddenly have a lot of work when it comes time to deploy your code to the site in production. Luckily, git is here to save you from wasting your time!

I'm going to go through this next part to get you up and running quickly, it is pretty easy to understand but too much detail is wasted here. Let's get a protected test repository up under a subfolder of our public website.

> cd ~/public_html/
> mkdir devsite
> cd devsite
> /usr/local/apache/bin/htpasswd -c ~/.htpasswd admin
<enter your password twice, for use with accessing your dev site securely>
> vi .htaccess

Our .htaccess file should be filled like so:

AuthUserFile /home/{username}/.htpasswd
AuthGroupFile /dev/null
AuthName "Dev Site"
AuthType Basic
require user admin
RewriteRule ^\.git - [F]

 This .htaccess file allows us to password protect our devsite folder (make sure to replace {username} with your actual username in this case) so crafty individuals can't see our development site (they don't want to see a bunch of tests anyways!). We also have a rewrite rule to prevent access to our git files, this is a good habit for git repositories that are accessible via HTTP that you do not want others to access.

Let's get a skeleton project underway.

> touch index.html
> echo "Hello world" > index.html
> git init
> echo ".htaccess" > .gitignore
> git add .
> git commit -m "Initial commit"

We've created a git repository with an index.html file with the contents "Hellow world" and we have told git to ignore our .htaccess file since it isn't part of our working codebase. Any files that you do not want git to track, just add their path to .gitignore on a new line, simple!

So far, nothing new & exciting. That comes next. We'll create a "bare" repository as sort of a central nervous system to our deployment scheme. It is recommended to put this repository somewhere outside of your web accessible files.

> mkdir ~/git
> cd ~/git
> git clone --bare ~/public_html/devsite

With the `git clone --bare` command, we are able to mirror our devsite repository in to a directory called "devsite.git", this is essentially a git repository without any of the live working files. It does, however, have all the necessary information to reassemble the working files, so it can act as a sort of exchange hub for our needs. We can push information to the "bare" repository, and once we've committed all of our changes, we can then pull the information to our devsite, or production site as the case may be.

The Final Touch

For this part, you will need git installed on your local computer. You can find everything you need at http://git-scm.com/.

From your local computer, clone your git repository. Using the git bash (or terminal for linux users), it can be done like so:

> git clone [email protected]:git/devsite.git

Once you have the repository on your local machine, make a few edits, add a file if you like. Do whatever you will to the files, in our case we changed "Hello world" to "Hello Dave" for testing the functionality. Next, we want to commit these changes to our local repository, and then push them to the remote repository. To do this, we need to add a remote git connection for git to reference with the `git remote` command.

> git remote add cns [email protected]:git/devsite.git
> git add .
> git commit -m "Updated the site"
> git push cns master

What we've done is aliased a remote repository locally, in this case we used "cns" as our alias. We committed our changes to the current repository, and then pushed our changes to cns from master (our current working branch).

At this point, our central nervous system repository ("devsite.git") has all the information we have on our local computer. To go from here to the devsite is easy, fire up SSH, and run the following:

> cd ~/public_html/devsite/
> git remote add cns ~/git/devsite.git
> git pull cns master

Your changes are now live on the devsite! This is certainly an extremely simple example, but from  here on in, a few lines of git jargon will get your batch of changes ready for testing. No messing with filesystem readouts or anything like that. Branches further sweeten the pot. Let's see we can do with branches, again with an extremely simple example.

On our local machine, let's create a new branch of our devsite, called "lost".

> git branch lost
> git checkout lost

Now I have changed index.html again to read: "Don't tell me what I can't do!" and committed my changes. Committing to a new branch is the same as always, issue the `git commit` command while the branch is active. You can determine the active branch by issuing the `git branch` command without parameters. Now that my local branch "lost" is ready, I'm going to push it to our intermediary repo, the central nervouse system of sorts.

> git add .
> git commit -m "We have to go back."
> git push cns lost

Tada, we now have an additional branch at the devsite.git repository. Now check out the the magic, we're back on the webserver now, via SSH:

> cd ~/public_html/devsite/
> git branch lost
> git checkout lost
> git pull cns lost

We just went live on the dev site with our changes, but what if we want to go back? Easy!

> git checkout master

What about merging the changes in lost to the master branch? Also easy:

> git branch master
> git merge lost 

There are many more ways to use git, this is just one. There are even methods for making this setup more automated, but I prefer to keep the HTTP-accessible repository on a short leash by running git commands directly there. If you work from only one location, you might find it easier to `git push` from your local computer to both the cns and devsite repositories, but this requires a little more work to keep tidy.

That's it! Whew!

Hopefully you have found a new way to keep the reins on your site, increase productivity, and better manage your codebase. Incorporating version control in to site deployment can be extremely powerful, easy, and time saving. There are many other applications for git, but I like to think this is one of the coolest for users on shared hosting. Try it out! Let us know how it works for you or drop us a line on more great git ideas.