Background (Skip if you just want the steps)
I had recently learned that I could setup a Git workflow to manage my personal site, and so I set out to do so by following some guides I found. After 9 hours and many StackOverflow answers, I finally managed to combine the information that was scattered across the Internet to make it work for me.
This guide is fairly long compared to others that will essentially take you to the same place. However, I find it immensely helpful when I understand what I’m doing instead of just blindly copy pasting commands into my terminal. Each step goes into “the why”, and since this aimed at beginners there is a lot to cover. If that’s not your cup of tea, I’m sure you could find a much more straightforward and compact tutorial.
Why do this?
My regular workflow to update a site usually goes something like this:
- Make changes locally and test until I implement whatever feature I want (multiple times)
- Push changes to Github (multiple times)
- FTP into my server and copy over the files from my local directory to my live directory
1 and 2 are things I do constantly with Sublime Text and Terminal, but 3 is a little detached from my general day to day workflow. I don’t make live changes nearly as much, and unless you’re crazy in love with Terminal already, you use an FTP client like I do to drag and drop these files over from your local machine to your hosting server.
As someone who is still getting comfortable with Terminal, but wants to incorporate it more into my workflow, this is a guide that will help you set up deployment to a site through the terminal, allowing you to ditch the FTP client.
I’m going to assume you know how to use Git at a basic level, have used an FTP client before, and know some basic Terminal commands. While this guide is for beginners, it’s definitely not for people new to version control and web development in general. That being said, I’m going to try to go into as much depth as I think necessary.
I’m using a Mac and I’m currently using Dreamhost for my hosting. Things might be different for you if you’re on Linux/Windows, and I can’t really help you if you are. Linux is fairly similar though, so it shouldn’t be too different. I will list the new terminal commands used in each section with a short description of what is happening. If you want more info, you can type man ARG and the manual page for the command will display in your terminal. You can press ‘q’ to go back to your regular terminal session. You can also use this handy site to search for Terminal commands and get an in-depth explanation about them as well.
1. SSH (Secure SHell)
SSH is a way to log into the terminal of a remote machine. You can use it to do things you would do on your computer (create new directories, copy files, etc.) but on someone else’s computer. However, before you can use it, you need to make sure it’s enabled for the server you’re trying to connect to. Dreamhost has a straightforward guide here that I used to enable it. It was essentially going into the control panel and just checking a box for SFTP to be turned on.
Once it’s enabled, you can initiate a connection:
ssh USERNAME@YOURDOMAIN.COM
You’ll be prompted for the password that you use to log onto the server. Once you’ve connected, you’re essentially able to do the same things you would do using your FTP client, but through Terminal.
This is neat, but it will get annoying really quickly if you have to keep typing in your password everytime you want to SSH into your server. Let’s set it up so you don’t have to.
To close the connection, you can type “exit” and press enter.
Terminal Commands Used
ssh: Opens an SSH connection.
2. Passwordless Login (Optional)
The first thing you’ll have to do is generate an RSA private key using ssh-keygen:
ssh-keygen -t rsa
You will be prompted for three things, and you can just hit enter to default the values.
Next, you will have to copy the public key to your server. On Macs, there’s a long but handy command on the Dreamhost wiki to do this all at once:
([ -f ~/.ssh/id_rsa.pub ] || ssh-keygen -t rsa ) && (ssh USERNAME@EXAMPLE.COM "([ -d ~/.ssh ]||mkdir -m 700 ~/.ssh) && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys" < ~/.ssh/id_rsa.pub)
Make sure you change the USER@EXAMPLE.COM to what you used to your credentials (same as previous step).
Let’s check if it worked with SSH
ssh USERNAME@YOURDOMAIN.COM
ls -a
You should see a new directory named .ssh, which will have an authorized_keys file inside.
(Alternatively, use your FTP client to check for the file.)
You should now be able to SSH into your server without being prompted for your password! Exit your session (type “exit”) and log back in. You might have to put in your password again, but after that, the next time you log in you shouldn’t need to.
Terminal Commands Used (The movement command I’m not even going to try to decipher)
ssh-keygen -t rsa: generates an RSA private keyls -a: lists all files in the current directory, including hidden files
3. Your Local Repository
You probably have a local repo set up and ready to be transferred to your server, but let’s start fresh and make a new one just in case. You can obviosly skip these steps if you want to use your own.
When applicable, I’m going to preface sections with [Local] or [SSH], indicating where you should run the commands. [Local] means in the regular Terminal that affects your machine, and [SSH] means you should run the commands while you are connected via SSH to your server.
[Local]
mkdir website
cd website
git init
touch index.html
sublime index.html
I have it set up so that I can run a command that will open up a file in Sublime Text, which you can also do here. Use whatever editor you like, or open it manually by locating the file through Finder.
Once you have the file open, modify it in some way (or don’t, it doesn’t actually matter), save and close it. We just want some sort of change in our repo so we can add and push the changes with Git, and creating the index.html file already fulfilled that requirement.
Let’s add the new file and commit the changes:
[Local]
git add index.html
git commit -m "Initial commit"
Your new repo is now ready to be pushed to Github, and more importantly it’s also ready to be pushed to your server! Let’s set up things on the server side so it’s ready to accept our local repo.
I recommend opening a new Terminal window (CTRL+N) and using that for your SSH connection for the following sections. There is a bit of back and forth so it’s nice to have the ability to switch between your local machine terminal and your server terminal quickly.
Terminal Commands Used
mkdir website: creates a new directory in the current directory named “website”cd website: changes into the directory “website”git init: initializes a git repo in the current directorytouch index.html: creates an empy index.html file in the current directorysublime index.html: a custom command that has SublimeText open the index.html filegit add index.html: adds index.html to the git staging areagit commit -m "Initial commit: commits any files in the staging area with the commit message “Initial commit”
4. The Remote Repository
Now we’ll set up the remote repo and what’s called a Git Hook. Without going into too much detail about hooks, they are essentially scripts that will run when you do things with Git. The hook we’re interested in is called the post-receive hook, which will execute once the remote repo receives a push from our local repo.
Now, since I am using Dreamhost, my server already had a directory named summitpatel.com on it, which is the domain I registered with them. Inside that directory is where I initialized my remote repo. If you are using a slightly different setup, you might need to create a directory first, which is what these next few commands do.
[SSH]
mkdir public_html/YOURSITENAME.COM/
cd public_html/YOURSITENAME.COM/
git init --bare
A bare repo doesn’t have a working tree or branch attached to it. It’s essentially just good for pulling changes from somewhere else, or for pushing changes to it. This is good, since that’s all we want to do with it, but it’s going to cause a problem later down the road for us. I’ll cover it when we get reach that point however, so don’t worry!
If you’re not good at Vi or Nano or some other bullshit in-terminal editor like myself, then at this point, you’re going to have to use your FTP client. Fire that baby up and we’ll set up the post-receive hook I mentioned earlier.
Terminal Commands Used
git init --bare: initializes a bare git repo in the current directory (more info about bare git repos here)
5. The post-receive Hook
Navigate through your directory to .git/hooks and locate the “post-recieve.sample” file. You should be able to right-click and edit the file with your text editor, and inside you will see a lot of lines inside that are commented out. You can ignore them or overwrite them, but inside you should paste the code found here. Save and exit once you’re done.
You don’t have to read through the script if you don’t want to, but what it essentially does is updates the files in the folder to the most recent commit, which will be the one you push from your local machine.
Lastly, you will need to rename the file to something other than “post-receive.sample”. I just removed the “.sample” part and left it as “post-receive”. This is important, otherwise your script won’t execute.
That should be the last thing we need the FTP client for. Let’s go back to the SSH Terminal window so we can change the permissions of the “post-receive” file so that it can actually execute, and then the hook is good to go.
[SSH]
chmod +x .git/hooks/post-receive
Terminal Commands Used
chmod +x .git/hooks/post-receive: change the file mode of the “post-receive” file to be executable
6. The Remote Path
Now we need to setup the remote path on our local machine so we can push the changes we make to our server. You can name the remote whatever you want, but you’ll probably want it to be something logical like “web” or “production”. I named mine web.
The path is a little tricky, because it will default the user to whatever user you are on your local machine if you don’t explicitly specify one.
[Local]
git remote add web ssh://USER@SERVERNAME.COM/home/USER/summitpatel.com
Notice that you will need your username twice in that line, not just at the beginning for the SSH. This is a typical Dreamhost path so you might need to modify it a little if you’re doing something different.
Let’s test if it worked!
[Local]
git push web +master:refs/heads/master
Remember that error I said we would run into earlier? Well, it’s finally here. We can’t push to our remote because it’s bare and Git doesn’t have a tree or branch to attach to. However, we can still override this and it will be perfectly fine for our needs.
[Local]
git config core.bare false
This will suppress the error we get and will allow us to push to our remote! Try pushing your changes again and they should go through this time.
Terminal Commands Used
git remote add web ssh://USER@SERVERNAME.COM/USERNAME/home/summitpatel.com: adds a new remote with the specified URL and gives it the alias “web”git push web +master:refs/heads/master: pushes your local master branch to the remote master branch (more info here)git config core.bare false: Disables the warning we receive in the terminal about pushing to a bare repo
7. Wrap up
From now on, all you’ll have to do when you want to update your site with local changes is run the git push web master command from terminal. This is such a huge boon when your normal workflow already consists of pushing changes to Github, allowing you to completely bypass opening your FTP client and dragging and dropping files inside.
I hope this has been insightful. I tried to make this as much as a “one stop shop” as possible, since I personally had to hunt around the Internet to gather all this information and put it all in one place and I hated it.
Here’s a list of sites I used to compile all of this information together:
- http://www.blog.philiptutty.com/?p=93
- http://toroid.org/ams/git-website-howto
- http://ryanflorence.com/deploying-websites-with-a-tiny-git-hook/
- http://wekeroad.com/2011/09/17/deploying-a-site-with-git-hooks
- http://stackoverflow.com/questions/8985782/git-push-fails-refusing-to-update-checked-out-branch-refs-heads-master
- http://danielmiessler.com/study/git/#commands
Setup with Yeoman (Optional)
Since I’m using Yeoman, there’s a small extra step that might not be entirely obvious to beginners. When you run grunt build, Yeoman creates a dist directory for you that is optimized for publishing. Push this directory to your server, and then go to your hosting and make that the web directory. For Dreamhost, you can do this by going to Manage Domains. Edit the domain you want, and then add /dist to your Web directory URL. Wait a few minutes and you’re all set!
Let me know if you have any questions or see any errors.
No comments:
Post a Comment