I was once in a hurry to share GitHub repository with a colleague who didn’t have access to it and we decided to use local git-daemon. However, handling all the little quirks that would make it work took a lot more efforts than just dropping a repository archive via Skype.From this article you will learn how to easily share read/write access to the local git repository. Additionally, I will share two simple aliases for git that will make this task a real no-brainer for anyone.
Disclaimer
Please note that this is an insecure way of sharing access to git repository and should be used only in a friendly LAN-environment. If you need secured solution, consider using
SSH-protected way.
Sharing read-only access
Next command shares read access(clone/pull) to any repository in current directory:
$ git daemon --base-path=. --export-all --reuseaddr --informative-errors --verbose
Where:
- –export-all – shares all the repositories in a folder from “–base-path” option
- –base-path=. – daemon looks for repositories in a current directory(“.”)
- –reuseaddr – allows to restart server quickly
- –informative-errors – provides cleaner error message for clients
- –verbose – notifies about each operation with the repository
Sample flow
1) Run git-daemon in directory with your repos:
$ cd my-repos
$ ls
facebook-killer better-twitter instapound
$ git daemon --base-path=. --export-all --reuseaddr --informative-errors --verbose
[8322] Ready to rumble
2) Now clients can clone/pull this repository:
$ git clone git://127.0.0.1/facebook-killer
Cloning into 'facebook-killer'...
remote: Counting objects: ...
...
$ git pull
Already up-to-date.
Instead of the “127.0.0.1” client should use the IP of your computer.
Sharing push access
Add “–enable=receive-pack” option and git-daemon starts supporting push access:
$ git daemon --base-path=. --export-all --enable=receive-pack --reuseaddr --informative-errors --verbose
There is one quirk: client can’t push into your active git branch. Before pushing, user on the server should change the branch, if client wants to push to this branch.Another option can be for the client to create a new branch and push it to your server. Then you can merge it into a required branch.
Sample flow
1) Run git-daemon in read/write mode:
$ git daemon --base-path=. --export-all --enable=receive-pack --reuseaddr --informative-errors --verbose
[8322] Ready to rumble
2) Client clones repository:
$ git clone git://127.0.0.1/facebook-killer
Cloning into 'facebook-killer'...
remote: Counting objects: ...
...
3) Client branches-off, makes changes and pushes back new branch:
$ git checkout -b sharing
# made some changes ...
$ git commit -am "add sharing feature"
$ git push -u origin sharing
...
* [new branch] sharing -> sharing
...
4) Now on Server you can merge this branch:
$ git checkout master
$ git merge sharing
Sharing only one repository
If you want to share only some repositories, you’ll need to remove “–export-all” option and create “git-daemon-export-ok” file in .git directory of the appropriate repositories.
Sample flow
1) Create magic file:
$ cd my-repos
$ ls
facebook-killer better-twitter instapound
$ touch facebook-killer/.git/git-daemon-export-ok
2) Run git-daemon without “–export-all” option:
$ git daemon --base-path=. --enable=receive-pack --reuseaddr --informative-errors --verbose
3) Client can’t access non-shared repository:
$ git clone git://127.0.0.1/better-than-twitter
Cloning into 'better-than-twitter'...
fatal: remote error: repository not exported: /better-than-twitter
4) Client can access shared repository:
$ git clone git://127.0.0.1/facebook-killer
Cloning into 'facebook-killer'...
remote: Counting objects: ..., done.
...
Making life simpler with aliases
Let’s create git aliases for read-only and read/write sharing. Here is what it should look like in .gitconfig:
# .gitconfig
[alias]
serve = !git daemon --base-path=. --export-all --reuseaddr --informative-errors --verbose
hub = !git daemon --base-path=. --export-all --enable=receive-pack --reuseaddr --informative-errors --verbose
# ...
Notice “!”-symbol in front of the aliases. This is a way to alias external shell command, and with this trick we can call these commands outside of git repository.Next commands automatically put these aliases into .gitconfig:
$ git config --global alias.serve '!git daemon --base-path=. --export-all --reuseaddr --informative-errors --verbose'
$ git config --global alias.hub '!git daemon --base-path=. --export-all --enable=receive-pack --reuseaddr --informative-errors --verbose'
Now with “git serve” you can share read access and with “git hub” – read/write access to our repositories. “git serve” resembles Mercurial “hg serve” which performs exactly the same operation. And “git hub” feels to be just right for read/write sharing, don’t know why.Once the aliases are added, we can run and see “hub” command in action:
$ git hub
[19178] Ready to rumble
Yay, it works!That’s it, and as I promised – it’s a real no-brainer to share anything using these magic aliases.