4. November 2011 10:07
(Updated July 15 2012. much of the information presented here is now obsolete -- check out my updated guide.)
This is a quick and dirty guide. YMMV.
I was motivated by the following:
- I want to work on and publish my website from several different machines, running different operating systems, with a minimum of fuss.
- After saving any changes to my central repository, I ideally want to see those changes with only a refresh of my browser.
- FTP publishing is generally clunky as hell.
- I’d done a similar thing before for a client, using SVN, and it worked well.
- Git is great.
- Whilst GitHub is fantastic, it costs money for private repositories and I would rather not pay for something when I can use my own VPS.
- Auto-publishing to my web server would be more difficult if my code was hosted on GitHub, anyway.
Setting up a Git server on Windows
This part is heavily inspired by the excellent and detailed guide by Tim Davis. Since writing, some of his steps have changed and/or are unnecessary and/or I chose to do them in a slightly different way. If you run into any problems with any of the steps listed here, please check out his guide for some solutions to common issues. Here follows a brief summary of what I did:
Download and install COPSSH to C:\ssh.
Create a new Windows user (optional; you can enable SSH access for an existing user if you prefer).
Open COPSSH Control Panel –> Users –> Add. Enter details for the user account <user> you want to enable SSH access for. Choose Linux shell + Sftp. I chose to allow both password and public key authentication.
Add a new inbound rule to the Windows Firewall to allow SSH traffic in (port 22, unless you changed it).
Add your public key to C:\ssh\home\<user>\.ssh\authorized_keys (create if needed). If you need to generate a public/private key pair, use PuTTYgen.
Test that everything is working so far by attempting to connect from another machine.
Download and install msysgit (at time of writing, Git-18.104.22.168-preview20111027.exe is the file you want) to C:\git.
Open C:\ssh\home\<user>\.bashrc and add the following to the end of the file:
Copy git-receive-pack.exe and git-upload-pack.exe from C:\git\libexec\git-core to C:\git\bin.
Verify that everything works by initialising a bare repository, cloning it, and pushing some changes. If you have a repository in C:\ssh\home\<user>\test.git, it can be accessed via ssh://<user>@<hostname>/ssh/home/<user>/test.git (TODO: find out why it’s rooted at /ssh). The following command-line session is fairly representative of success:
peterdn@ubuntu:~$ ssh 192.168.61.131
Last login: Thu Nov 3 21:45:58 2011 from 192.168.61.130
$ mkdir test.git
$ git init --bare test.git/
Initialized empty Git repository in C:/ssh/home/peterdn/test.git/
Connection to 192.168.61.131 closed.
peterdn@ubuntu:~$ git clone ssh://firstname.lastname@example.org/ssh/home/peterdn/test.git test
Initialized empty Git repository in /home/peterdn/test/.git/
warning: You appear to have cloned an empty repository.
peterdn@ubuntu:~$ cd test
peterdn@ubuntu:~/test$ echo hello > hello.txt
peterdn@ubuntu:~/test$ git add hello.txt
peterdn@ubuntu:~/test$ git commit -m "initial commit"
[master (root-commit) 64f843d] initial commit
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 hello.txt
peterdn@ubuntu:~/test$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 219 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
* [new branch] master –> master
Setting up a repository for auto-publish
Now that we have our Git server up and running, we can begin to invoke the black magic required to implement auto-publishing. This part of the guide will be purely by-example; your setup with undoubtedly differ from mine, but hopefully the principles remain the same. My desired setup looks like so:
- Git repository is located in C:\inetpub\git\mysite.git.
- Website is located in C:\inetpub\wwwroot\mysite.peterdn.com. This is a clone of the above repository.
Note: for some reason that I’m yet to fathom, my git*.exe binaries live in a different virtual directory environment to the shell, and of course, Windows. For example, what my shell thinks is /home/peterdn, git.exe thinks is /c/ssh/home/peterdn. This has turned out to bite me a couple of times, but if you’re aware of the problem, it might make things easier to diagnose.
In C:\ssh\home\<user>, create a symbolic link to C:\inetpub\git, using the following command:
mklink.exe /D git C:\inetpub\git
Similarly, create a symbolic link to C:\inetpub\wwwroot.
Make sure that <user> has appropriate permissions for C:\inetpub\git\mysite.git and C:\inetpub\wwwroot\mysite.peterdn.com.
Due to the bizarre path problem mentioned above, and the fact that I’d cloned <website> from within cmd.exe, my remote config currently looks like:
$ git remote -v
origin C:\inetpub\git\mysite.git (fetch)
origin C:\inetpub\git\mysite.git (push)
This will make things unhappy if we attempt to pull from origin in the Cygwin environment. Therefore, I added another remote:
git remote add local /c/ssh/home/peterdn/git/mysite.git
Now we add the hook that will automatically pull changes whenever the main repository receives changes. Add the following to C:\inetpub\git\mysite.git\hooks\post-receive:
git pull local master
Verify that it works by pushing some changes.
The results of the above are sufficient for the moment. However, there are a few things that I would consider changing or adding in the future:
- Remove the requirement for the /ssh/home/<user>/git component from the URL, as it looks messy and is just generally bad form.
- Sort out issues with different virtual directory structures.
- Have a separate website for testing out changes without having to mess with the live site. I assume this is simple as having separate “stable” and “current” branches, and pulling from these to the appropriate places. But I could be wrong.
- Remove the .git directory from my web root. I believe this is possible using a detached work tree.
- GitHub-style web interface for managing my repositories.