Git in the classroom: cloning/pushing exams in programming courses

7 minute read Published: 2010-10-30

I had to apply an exam this week for a web development for beginners course I'm teaching. We're using ruby for the server side for a couple of reasons: heroku is an excellent option for one's first deployments and I wanted to get a better grip on Ruby on rails 3 and html5 for my own improvement (and I've found that there's no better way to learn stuff the good way than teaching them).

No decent developer can survive without some sort of source control management. The one I know more of is git and I'm a huge fan of github. We're actually using github organizations to manage the class projects (the github staff is really great, they've let me use private repositories for the student groups at no extra charge).

The exam for this period was a practical one: I gave them a site (that I wrote and deployed on heroku) and they had to reproduce it's functionality in a day. I like that kind of exams: they're a learning experience themselves. But the week before it, i found myself re-thinking the delivery method. You see, back in the day, those kinds of exams were either sent to the teacher by email or uploaded to the college's private file server. I wanted my students to practice their git so my first thought was to ask them to upload their solutions as a git bundle to our course communication platform, yet, after that, I thought: "hey, wouldn't it be cool that they could just git push their exam and be done with it". The idea was compelling: instead of waiting till the end of the day -the exam deadline- to upload their exams, they could just push as many times they wished and the last push they made before the deadline was going to be considered as their final response. Motivated by this, I dedicated the days before the exam to it.

The first thing I needed was to have 15 private git repositories available, with read/write access to just myself and each individual student. I didn't want to ask the github guys for even more private repos, which would be active for just a couple of days and I wanted to learn more about git and what hosting git implies, so I bought a vps from and installed gitosis. I asked the students to email me their public ssh keys and added them to my gitosis admin. I must say, gitosis is the raddest thing: it lets me easily manage git repositories without even having to login to the remote server, just pushing changes whenever I'm ready.

Now, my first idea -and one I will definitely keep working on- was to have a web interface that would let me create an exam, assign it to users and give it a start date and it would create the repositories and even add/remove the users from the writers list on the gitosis configuration file when the dates would necessitate it - the gitosis web admin project gave me the idea. Sadly, I had no time for that and had to do it by hand -which is pretty easy, anyway.

I also wanted to have an interface like the github dashboard to have quick feedback for when a student pushed their solution and what files they updated (because, being their first incursions into git and scm in general, they could easily forget to add files). I remembered the notion of hook in git and read the documentation: there is a hook called post-receive which is a script that will be called upon a successful push. Just what I wanted. So I created a ruby script that would post to a sinatra app information about the push - I got that idea from the github post-receive hooks service.

Now, I have the conviction that when one finds himself repeating a task that could be automated one is betraying his reason, so, even though I could just create the 15 repos by hand and then add the post-receive hook to each of them, I modified the git template on the server (located in /usr/share/git-core/template by default) to add the hook and then wrote a ruby script to use grit to fork a template directory (which contained a readme with the exam requirements and some helper files) 15 times, naming the repositories after the registry number for each student.

So at the end I had the 15 private repos forked from a template that could be cloned by each student with all the privacy needed (only I and the owner of each repo could read/write from it) and post-receive hooks to follow the progress of the students during the exam. I did this in three days and it was remarkably easy, because of such amazing projects as gitosis and grit.

I had my share of trouble, though: first, one day after acquiring the vps over at I found myself victim of a man in the middle attack in ssh: I was doing tests with the gitosis server when, while pushing a repo, I was warned that "someone could be doing nasty stuff". I logged in to the server and checked the ssh files (which, if changed, could change the fingerprint and, thus, be detected as an intrusion in the communication), they weren't changed. So I found some advice on the internerd that changing my ssh port to a non-standard one and restricting access by keys and users could avoid that kind of attack. I applied it and solved it, but that meant that yesterday I had to invest some minutes of the exam asking the students to change their ssh configuration to connect via the other port -not the 22- to my git server. Solving that required a couple of angry hours. But it wasn't the end of the problems: close to the deadline some students contacted me saying that when trying to push they were receiving a connection refused error. I had experienced that the day before when working in college, but attributed it to the firewall. I am not sure as of today, but it seems that it was actually an error in the server side: one had to push like twenty times before the server accepted the connection, so some students ended up sending me their work via email after all.

Nevertheless, I really like the idea of using git to apply evaluations, and am thinking of creating a web interface to let teachers create exams/homeworks that will translate into private git repos to which the students could push. There are some parts of the process I'd like to automate and simplify (I'd like to offer the service to people that know enough git to clone/pull/push , but have no time to set up private hosting servers and stuff) and there are two more exams to come for this class, so I'll keep experimenting. I'm a little concerned about prgmr, though, I was attacked twice (the first time with a dictionary attack before I even logged in for the first time) and had that unfortunate incident with the sshd (which could be my fault or because of the technical limitations of the vps I chose). In their defense, they have a really cool customer support (they don't assume you are stupid and answer really fast).