Setting up a git repository on a LAN under OS X

I decided to embrace distributed version control. I’ve been using Mercurial a little because of the Cocotron project¬†on Google Code. But since git support is built in to Xcode 4, I decided to use git for my own projects so that I’ll be ready on the day when I switch to Xcode 4. I had already set up a Subversion server on my development machine at work, so I figured setting up a git server wouldn’t be too difficult. For the most part it wasn’t, but there were a couple stumbling blocks that I’m going to document here to help others trying to do the same thing (and my future self when I need to set up a git repository on another machine).

My need is for a repository server on a local LAN where I’m not worried about malicious users. So I don’t need to concern myself with access over the Internet or ssh. Here’s what I did:

  1. Install git. This is documented in plenty of places.
  2. Put source code in a shared location. In my case I put it in a folder in /Users/Shared/git.
  3. Create the git repository (This step turns out to be wrong, but gets fixed later.):
    git init
    git add .
    git commit
  4. Set up the git server. Create a file called git.plist in /Library/LaunchDaemons with the following content:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
    	<key>Label</key>
    	<string>git</string>
    	<key>OnDemand</key>
    	<false/>
    	<key>ProgramArguments</key>
    	<array>
    		<string>/opt/local/bin/git</string>
    		<string>daemon</string>
    		<string>--export-all</string>
    		<string>--base-path=/Users/Shared/git</string>
    	</array>
            <key>ServiceDescription</key>
            <string>git Version Control System</string>
    </dict>
    </plist>
  5. Clone the repository:
    git clone git://machinename.local/projectname projectFolderName
  6. After making changes, commit them locally:
    git commit -a
  7. Now push them to the repository (and experience the first error):
    git push
    gives the error:
    fatal: The remote end hung up unexpectedly
  8. This is because the default settings for the git daemon allow only read access. To enable write access, add this string to programArguments array in git.plist:
    --enable=receive-pack
    So now git.plist looks like this:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
    	<key>Label</key>
    	<string>git</string>
    	<key>OnDemand</key>
    	<false/>
    	<key>ProgramArguments</key>
    	<array>
    		<string>/opt/local/bin/git</string>
    		<string>daemon</string>
    		<string>--export-all</string>
    		<string>--base-path=/Users/Shared/git</string>
    		<string>--enable=receive-pack</string>
    	</array>
            <key>ServiceDescription</key>
            <string>git Version Control System</string>
    </dict>
    </plist>
    To get this change to take effect, either reboot or execute the following commands in Terminal:
    cd /Library/LaunchDaemons
    sudo launchctl stop git
    sudo launchctl unload git.plist
    sudo launchctl load git.plist
  9. Try again to push (and experience the second error):
    ! [remote rejected] master -> master (branch is currently checked out)
  10. Stack Overflow to the rescue!
    git config --bool core.bare true
    Then hold breath while deleting all files except .git directory in repository folder
  11. A working git repository

Some helpful links: