@Tim This is essentially the same solution, but squeezes the content of my ~/gitserve script into authorized keys by using perl. Personally, I prefer keeping it in a separate script.
–
Neil MayhewApr 4 '12 at 22:32

git-shell is designed to be used as a login shell, so that it would receive -c "originalcommand" as arguments. This doesn't happen with "forced commands" in OpenSSH; instead, the forced command is passed to the configured shell.

What you can do is write a script that checks $SSH_ORIGINAL_COMMAND and executes it. Example in bash:

Hmm... I made that change according to what I saw when I ran it. With both a bash script and a ruby script, I saw "git-receive-pack" as the command. Quote from my man git-shell (git 1.7.3.4): Currently, only four commands are permitted to be called, git-receive-pack git-upload-pack and git-upload-archive with a single required argument, or cvs server (to invoke git-cvsserver).
–
Matt ConnollyJun 23 '11 at 0:16

This doesn't work for me, because my git client (1.7.5.4) sends the repo name in single quotes, presumably because it's expecting to have the entire command line interpreted by a shell. The exec $SSH_ORIGINAL_COMMAND then passes the single quotes on to git-receive-pack etc. which therefore doesn't find the repository.
–
Neil MayhewOct 6 '11 at 15:50

Thanks for the solution, grawity, but it doesn't work for me, for the same reason that was reported by Neil Mayhew... my 1.7.x version of git also sends the repo name in single quotes, ultimately causing the $SSH_ORIGINAL_COMMAND to be invalid, and causing git-shell to bum out :-(
–
pvandenberkOct 13 '11 at 23:45

I couldn't get grawity's solution to work for the same reason that was reported by Neil Mayhew (ie. the single quotes sent by the git client causing an invalid $SSH_ORIGINAL_COMMAND -- I'm using git v1.7.x)