At work I wanted to set up a means for us to keep track of our software/website/code versions and still allow several people to access the code, but then to retain control over what gets pushed to production – and also to have a means of rolling back the production server in case something broke. The following is how I ended up deploying our git repositories for our institution. This post assumes you’ve already set up a git repository using gitweb or something similar (step #13).
Why this way?
The main concept here was to create a hub of code repositories where everyone in our IT department can view and examine all of our scripts and applications and allow all of our IT employees to download and examine the code either for review or to work on. Because the “hub” is where the code is pushed to from a local computer, I can examine any changes before they are pushed to production servers. This way code pushes can be scheduled, or can be pushed to multiple remote repositories simultaneously (think “Push Parties” and “Multi-Site Updates… by typing very little”).
What you’ll need to get started
You’ll be making changes to several systems, including your personal (“local”) machine, a git repo server, and the production server. You may also want to know the Git Basics.
git repo server
1. Log in to the git repo server and change to the root user and change to the repo directory
sudo su - cd /opt/git/projects
2. Create a “bare” repository and initiate a git repository
mkdir myreponame.git cd myreponame.git git init --bare
3. Go up a directory and make sure to change the ownership of the repository to “git” so you don’t run into permission problems later on, then change to “git” user.
cd .. chown -R git:git myreponame.git su - git
4. edit the description file to explain what the main purpose of the application or script is. Keep it fairly brief. See the vi_cheat_sheet if you need help with commands.
5. clone the repository from the git repo server. You’ll need to set up your system to access the git server via ssh keys. Here’s how if you’re using Eclipse.
6. Add the files you’ve been working on, and commit them. Then do a push to the main git repository. If you’re using Eclipse, here’s a good tutorial for using Egit.
remote “production” server
7. Log into the production server (e.g. mywebsite.com) as root and create a “git” user if not already present.
sudo su - adduser git passwd git
8. Create a bare repository in the git user’s account and change to that directory. It’s easier to remember if you name it the same as the repository on the git repo server
cd /home/git/ mkdir myreponame.git && cd myreponame.git
9. Inside the new bare repository change to the hooks/ directory and edit the post-receive.sample file and rename it (or just create a new one); what we are doing here is setting up a bash script that defines a work tree for the repository – even though it’s a bare repo – and then forcing a checkout to the work tree every time that the git repository receives a push. More information on the git environment can be found here.
cd hooks vim post-receive #!/bin/sh GIT_WORK_TREE=/path/to/web/accessible/application/directory git checkout -f
10. Make sure that the post-receive file is executable. If not, change it.
chmod 755 post-receive
git repo server
11. Switch to the “git” user and set up the git user to push to the production server via ssh keys and then copy the contents of the id_rsa.pub to the remote server.
ssh-copy-id -i ~/.ssh/id_rsa.pub git@remoteproductionserver
12. As “git”: Test the connection of your ssh keys. If all is well, you should get a listing of the git user’s home directory with the bare git repo you created while on the production server.
ssh git@remoteproductionserver ls -al
13. Since you pushed the contents of your local machine to the git repository, you can make sure that all the information is properly available by opening a browser and going to your gitweb install. You should see your repository listed among all the others and can browse the files that are in that repo.
14. As “git”: In the shell, move back to the location of the new repository (i.e. /opt/git/projects/myreponame.git) and add a remote alias so that it’s easier to push to the production server in the future
git remote add prod (or www, or live, etc) ssh://remoteproductionserver/home/git/myreponame.git
15. As “git”: Push everything to the production server. If everything went according to plan, you’ll find the contents of the remote production server’s “working tree” populated with your content. By working tree, I mean the web url of your content from step #9. You can verify it by opening a browser and checking out your handiwork.
git push prod master
rolling back changes in case a commit causes a fubar situation
16. As “git” on git repo server: To find out what change caused the problem, retrieve the latest commit hash (or the one you want to roll back to) from the disply of myreponame.git on your gitweb install. Essentially, by running this command, you’re moving the write HEAD back to the latest commit record and dumping the latest commit data (thereby deleting it from memory).
git reset --hard hashvalue (e.g. git reset --hard 4f886a33318f795ab36e32137d3297ecdbc0fd88)
17. Now you’ll need to push to the production server again, but you’ll need to force the overwrite because otherwise you’ll get an error about non-fast-forward updates and out of sync errors. The + indicates that you are forcing the push.
git push prod +master