Recently I’ve switched from using Subversion to using Git for version control on personal projects. Now as much as Windows annoys me—and believe it me when I say it does annoy me—I still prefer to use it as a development environment (for PHP or Java) over Ubuntu (which I used for that sort of thing for a year or two). There is a better selection of tools. The UI is better. And to top it off, Civilization 4 is easier to run on Windows.
Why Git?
There are quite a few comparisons between Subversion and Git out there. Ultimately they’re just different philosophies and approaches. For me it came down to:
- I like the Git philosophy of being able to distribute patches without creating history on your central repository. At work, doing a code review usually entails doing a checkin (and yes I know you can create svn diffs);
- Git allows you to push your changes to several repositories. This is great for redundancy. I’m paranoid about losing source code. Anyone who writes software should be paranoid about becoming the next Avsim;
- You can use Git for deployment to your hosting provider; and
- All the cool kids are doing it. :-)
That being said, Git does have some downsides:
- Subversion has better tooling and IDE integration;
- Getting Git to work right on Windows is a hair-pulling experience (which is the point of this post);
- With Subversion you are the user that’s set up for you in the repository. In Git, you are who you say you are, which takes a bit of getting used to;
- Obviously multiple repositories is by its nature more complicated than a single central repository; and
- Subversion deals with binary files better and easier than Git does.
One piece of advice I’ll give you is this: If your Windows username has a space in it, change it. I was bashing my head against a brick wall for awhile before I figured out that my Git commands were failing to remotely authenticate because the Python script didn’t handle the case where the username contained a space as best as I could tell.
Why Cygwin?
The nicest environment to have is one where you don’t have to type in your password every time you want to do a pull or push to a remote repository. Good security suggests you should do such things over SSH.
I wasted a lot of time with firstly the bundled git-bash and then with PuTTY. I had problems with git-bash like when doing a git push over ssh it would inexplicably hang. It also seemed to be leaking file descriptors or something because it reached a point where it wouldn’t connect to anything, not even things I’d successfully connected to.
PuTTY I usually use under sufferance. It does the job but I find myself just wanting a good command line (rather than say plink.exe and a command prompt).
Do yourself a favour and use Cygwin from Day One.
I’m currently using Cygwin 1.7.0 even though it’s in beta. When you install it, you have to select the packages you want. SSH (openssh) is not installed by default so select that under Net or search for it and select it.
One of the (many) nice things about Cygwin is that it creates a virtual filesystem for you where you can mount different directories at different points using the mount command. For example:
mount c:/xampp/htdocs /www
creates a convenient spot for your deployment directory.
If you’re not familiar with a Unix/Linux shell like bash and the typical Unix/Linux commands, do yourself a favour and get comfortable with them.
Why Projectlocker?
One of the things I wanted was a remote backup for my source code that is separate to my hosting account. Some may consider this overly paranoid. I think it’s good practice to have a local repository, your production code deployed on your hosting provider and a remote backup of your development work since that won’t necessarily be pushed to the hosting provider.
I compared several private hosting alternatives including the ever-popular Github, Unfuddle and Projectlocker. Their free version for me had the best features:
- Both Subversion and Git;
- Multiple active projects;
- Unlimited repositories;
- RAID storage and nightly backups;
- 500MB storage; AND
- SSL encryption.
These services all differ in what products they integrate (eg Wikis, bug/issue tracking, project management and so on) so you really need to do your own research to find what’s right for you.
The one downside of Projectlocker is their website is rather primitive and at times slow to respond (with certain pages). But once you’re set up you should have almost no need to go to it again.
Setting up SSH
Using public key encryption is far more convenient than being asked for your password every time you want to access the remote repository.
First, create a public key if you don’t have one already:
username@hostname:~$ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/home/username/.ssh/id_rsa): Created directory '/home/username/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/username/.ssh/id_rsa. Your public key has been saved in /home/username/.ssh/id_rsa.pub. The key fingerprint is: 63:17:a4:06:78:34:9d:4f:2d:4c:7f:8f:84:5a:4b:c4 username@hostname username@hostname:~$ cat ~/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArGyNxx5nct8vic01GxKPybSxL6ZNBMcOrtwo0dMSU0qN9l4pxAuX0jjJe4Pl/I121NztTDdiIntOTaYiQQXTQ2NP8MD5X1oyr7svs8Rm50zpQwOQ3rt4MvwgotZZjMoETT39fA3soRoQLQS5LzD0W7cvVdSoTGYcL+lfv2f0xQdS+CgCrRTeiwn7KYgD6arZLo6B1wVPCAmaiyo1Hetu1q7UIzh4dCACUy4BymlLAxon0NRWAhEADKltZqMitnPgDqtRXyMLUzEn6AvIotRprK7LoPzvLqz2MgBfzTne13Dz8LFOPhbM2n7cSf/OEUt+TtKZqvIoUb79smKDsf2aXw== username@hostname
Next, go to the Projectlocker Portal, login and if you haven’t done so already, create a Git repository. Your Git URL will be under “User Home” on the left hand menu. Also on the left-hand menu is “Manage Public Keys”. Click “New Key” and enter:

Save that and assuming everything has been done correctly you should be able to go to your local machine and type:
username@host:~$ ssh git-CompanyName@freeN.projectlocker.com PTY allocation request failed on channel 0 ERROR:gitosis.serve.main:Need SSH_ORIGINAL_COMMAND in environment. Connection to freeN.projectlocker.com closed.
You don't have shell access but as long as you don't get prompted for your password, it should all be working correctly. You can get more detailed information with:
username@host:~$ ssh -v git-CompanyName@freeN.projectlocker.com
or even more verbose:
username@host:~$ ssh -vv git-CompanyName@freeN.projectlocker.com
Local Git Repository
There are multiple ways of doing this. You can create a local repository and push it to Projectlocker or you can simply clone it, which is what I’ll do:
username@hostname:~$ git config --global user.name "Your Name" username@hostname:~$ git config --global user.email "youremail@example.com" username@hostname:~$ git clone git-CompanyName@freeN.projectlocker.com:project.git Initialized empty Git repository in /home/username/project/.git/ remote: Counting objects: 118, done. remote: Compressing objects: 100% (96/96), done. remote: Total 118 (delta 15), reused 111 (delta 15) Receiving objects: 100% (118/118), 184.08 KiB | 69 KiB/s, done. Resolving deltas: 100% (15/15), done.
Your output may look different as I'm cloning a populated repository in this case. The first two statements are telling Git who you are. Any commits will be identified by that name and user and this includes pushes to remote repositories. This is what I mean by Subversoin users needing to get used to this. Rather than being who the remote server authorizes you as, you are who you say you are.
An alternative way to set this up is:
username@hostname:~/work$ git init Initialized empty Git repository in /home/username/work/.git/ username@hostname:~/work$ git remote add project git-CompanyName@freeN.projectlocker.com:project.git username@hostname:~/work$ git pull project master remote: Counting objects: 126, done. remote: Compressing objects: 100% (102/102), done. remote: Total 126 (delta 17), reused 111 (delta 15) Receiving objects: 100% (126/126), 184.87 KiB | 78 KiB/s, done. Resolving deltas: 100% (17/17), done. From git-CompanyName@freeN.projectlocker.com:project * branch master -> FETCH_HEAD
Now try the following test:
username@hostname:~/project$ cat > test.txt This is a test ^D username@hostname:~/project$ git add test.txt username@hostname:~/project$ git remote origin username@hostname:~/project$ git commit -m "adding test file" [master 4811b38] adding test file 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 test.txt username@hostname:~/project$ git push origin master Counting objects: 4, done. Delta compression using up to 4 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 282 bytes, done. Total 3 (delta 1), reused 0 (delta 0) To git-CompanyName@freeN.projectlocker.com:project.git a6a6bf9..4811b38 master -> master username@hostname:~/project$ git rm test.txt rm 'test.txt' username@hostname:~/project$ git commit -m "getting rid of test" [master 172d57d] getting rid of test 1 files changed, 0 insertions(+), 1 deletions(-) delete mode 100644 test.txt username@hostname:~/project$ git push origin master Counting objects: 3, done. Delta compression using up to 4 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (2/2), 243 bytes, done. Total 2 (delta 1), reused 0 (delta 0) To git-CompanyName@freeN.projectlocker.com:project.git 3edc309..bccaeeb master -> master
Here we’ve simply added a test file, committed it, pushed the whole master branch back to Projectlocker and then removed it. The "git remote" class lists our remote repositories
Remote Deployment
To do this cleanly, you require SSH shell access to your hosting provider or remote server. Rather than I write this out myself, I shall point you to excellent Using Git to manage a web site as to how to set this up.
Conclusion
I hope you’ve found this guide useful. It can be a daunting task to figure out exactly where to start and how to begin with a new tool like Git, particularly because there are so many ways you can use it. I truly hope this saves you some grief in getting it set up and working on Windows.
15 comments:
Thanks for the article! Didn't really tried git yet, but indirectly learned about the public key in SSH, which will be a good timesaver in the future! :))
Excellent guide. I found this very helpful in getting set up on projectlocker today. It's certainly not the most intuitive site to use but it's good value for money :)
One little tidbit of info that you may want to know is this. I don't know if this is true or not but I read in a comment on another forum that projectlocker stores their passwords in plain text. I'm not sure it's a major concern but just thought I'd let you know.
ProjectLocker DOES NOT store passwords in plain text. I work at ProjectLocker, and wrote the relevant code. It stores passwords in a retrievable format (like Amazon or PayPal do with your credit card), but definitely NOT in plaintext. Please see the canonical response here:
http://superuser.com/questions/46810/should-i-be-concerned-if-my-git-hosting-provider-stores-passwords-in-plaintext/46951#46951
Thanks!
Excellent article !!!
ProjectLocker should DEFINITELY have it on there website.
Thanks VERY VERY much !
yeah, another sincere Thank You.
addendum: for getting set up with PL i had to push remote first, not pull the way it appeared to me your instructions were saying.
I am getting this error. Any suggestions
$git push origin master
fatal: The remote end hung up unexpectedly
The above instructions for creating your repository are not very good.
Here's a easier run-down:
= name you want to call the remote repository
= git-yourcompany@blah.projectlocker.com:project.git (copy/paste from the User Home page)
a) [go to your local source code directory]
a) git init
b) git remote add
c) git add *
d) git commit -am "initial commit"
d) git push master
The above instructions for creating your repository are not very good.
Here's a easier run-down:
{name} = name you want to call the remote repository
{url} = git-yourcompany@blah.projectlocker.com:project.git (copy/paste from the User Home page)
a) [go to your local source code directory]
a) git init
b) git remote add {name} {url}
c) git add *
d) git commit -am "initial commit"
d) git push {name} master
That is Good, thank you very much
But I have a problem here in the test step. I don't know why your test contains hostname@hostname: ??? mine not.
anyway thanks.
@Ahmed that's a typo on my part. It should be username@hostname. Thanks for pointing it out and glad you liked the post.
Thanks for your concerning and fast reply.and for deleted post.
But I still can't do any upload or any other test. In your post, your machine has username@hostname:~/project$, but mine only has username@hostname ~$, so when I use cat > test.txt, it didn't work
my code :
"ahmed@ahmed-PC ~
$ cat > test.txt
[1] 13156
bash: gt: command not found
bash: test.txt: command not found"
And test.txt is a file in /home/ahmed/Assembler.
Assembler is my project name. If you can tell me what I can do,I will very very glad.
Thank you very much for your effort.
re: "being able to distribute patches without creating history on your central repository."
this is brain-dead
this alone is reason to avoid git and it's ilk at all costs
this is NOT version control; it is fanboi chaos
Thanks for this post, although it didn't help to solve my specific problem, it helped me to understand Git a bit better and lead me in the right direction. Finally cloned a repository successfully today! Thanks very much.
Post a Comment