Chapter 4. Git on the Server
1.? The preferred method forcollaborating with someone is to set up an intermediate repository that youboth have access to, and push to and pull from that. We refer to thisrepository as a Git server;It generally takes atiny amount of resources to host a Git repo, so you'll rarely need to use anentire server for it. A remote repository is generally a bare repository—a Git repository that has no working directory. Becausethe repository is only used as a collaboration point, there is no reason tohave a snapshot checked out on disk; it's just the Git data. In the simplestterms, a bare repository is the contents of your project's .git directory andnothing else.
?
$ git clone /opt/git/project.git
Or you can do this:
$ git clone file:///opt/git/project.git
Git operates slightly differently if you explicitly specifyfile://?at the beginning of the URL. If you just specify thepath, Git tries to use hardlinks or directly copy the files it needs. If youspecify file://?, Git fires up the processesthat it normally uses to transfer data over a network, which is generally a lotless efficient method of transferring the data. The main reason to specify the file://prefix is if you want a clean copy of the repository with extraneous referencesor objects left out—generally after an import from another version-controlsystem or something similar.
?
To add a local repository to an existing Git project, youcan run:
$ git remote add local_proj /opt/git/project.git
$ git clone ssh://user@server:project.git
Or you can not specify a protocol—Git assumes SSH if youaren't explicit:
$ git clone user@server:project.git
You can also not specify a user,and Git assumes the user you're currently logged in as.
?
$ cd /var/www/htdocs/
$ git clone --bare /path/to/git_project gitproject.git
$ cd gitproject.git
$ mv hooks/post-update.sample hooks/post-update
$ chmod a+x hooks/post-update
The post-update hook that comes with Git by default runsthe appropriate command (git update-server-info?) to make HTTP fetching and cloning work properly. Thiscommand is run when you push to this repository over SSH; then, other peoplecan clone via:
$ git clone http://example.com/gitproject.git
( http://www.kernel.org/pub/software/scm/git/docs/howto/setup-git-server-over-http.txt .)
$ git clone --bare my_project my_project.git
By convention, bare repository directories end in .git.This is roughly equivalent to something like:
$ cp -Rf my_project/.git my_project.git
There are a couple of minordifferences in the configuration file;
?
11.? If you've set up a server git.example.com that you have SSH access to, and you want to store all yourGit repositories under the /opt/git?directory. You can set up your new repository by copying your bare repositoryover:
$ scp -r my_project.git user@git.example.com:/opt/git
At this point, other users who have SSH access to the sameserver, which has read access to the /opt/git?directory, can clone your repository by:
$ git clone user@git.example.com:/opt/git/my_project.git
If a user SSHs into a server and has write access to the /opt/git/my_project.git?directory, they also automatically have push access.
Gitautomatically adds group write permissions to a repository properly if you runthe gitinit command with the --shared option:
$ ssh user@agit.example.com
$ cd /opt/git/my_project.git
$ git init --bare --shared
?/.ssh/authorized_keys?file of your new "git" user. At thatpoint, everyone will be able to access that machine via the "git"user. This doesn't affect the commit data in any way—the SSH user you connectas doesn't affect the commits you've recorded.
$ cat /tmp/id_rsa.John.pub >> ?/.ssh/authorized_keys
$ cat /tmp/id_rsa.josie.pub >> ?/.ssh/authorized_keys
$ cat /tmp/id_rsa.Jessica.pub >> ?/.ssh/authorized_keys
Then, you can set up an empty repository for them byrunning git init with the --bare option, which initializes therepository without a working directory:
$ cd /opt/git
$ mkdir project.git
$ cd project.git
$ git --bare init
Then one of the git users can push a home folder togitserver :
$ cd myproject
$ git init
$ git add .
$ git commit -m 'initial commit'
$ git remote add origin git@gitserver:/opt/git/project.git
$ git push origin master
At this point, the others can clone it down and pushchanges back up just as easily:
$ git clone git@gitserver:/opt/git/project.git
$ vim README
$ git commit -am 'fix for the README file'
$ git push origin master
git-shell?that comes with Git as your "git" user's loginshell, then the "git" user can't have normal shell access to yourserver:
$ sudo vim /etc/passwd
At the bottom, you should find a line that looks somethinglike this:
git:x:1000:1000::/home/git:/bin/sh
Replace it with something like:
git:x:1000:1000::/home/git:/usr/bin/git-shell
$ cd project.git/.git
$ mv hooks/post-update.sample hooks/post-update
$ chmod a+x hooks/post-update
The post-update looks basically like:
$ cat .git/hooks/post-update
#!/bin/sh
exec git-update-server-info
This means that when you push to the server via SSH, Gitruns this command to update the files needed for HTTP fetching.
Next, you need to add a VirtualHost entry to your Apacheconfiguration with the document root as the root directory of your Gitprojects:
<VirtualHost *:80>
??? ServerName git.gitserver
??? DocumentRoot /opt/git
??? <Directory/opt/git/>
??????? Order allow, deny
??????? allow from all
??? </Directory>
</VirtualHost>
You also need to set the Unix user group of the /opt/gitdirectories to www-data?so your web server hasread-access to the repositories, because the Apache instance running the CGIscript will (by default) be running as that user:
$ chgrp -R www-data /opt/git
$ git instaweb --httpd=webrick
That starts up an HTTPD server on port 1234.
?
You can set up the CGI script to be served by your normalweb server. To install GitWeb manually(Some Linux distributions have a gitweb?package), you need to get the Git source code andgenerate the custom CGI script:
$ git clone git://git.kernel.org/pub/scm/git/git.git
$ cd git/
$ make GITWEB_PROJECTROOT="/opt/git" prefix=/usrgitweb/gitweb.cgi
$ sudo cp -Rf gitweb /var/www/
Now, you need to make Apache use CGI for that script, forwhich you can add a VirtualHost:
<VirtualHost *:80>
??? ServerName gitserver
??? DocumentRoot/var/www/gitweb
??? <Directory/var/www/gitweb>
??????? Options ExecCGI+FollowSymLinks +SymLinksIfOwnerMatch
??????? AllowOverride All
??????? Order allow,deny
??????? Allow from all
??????? AddHandler cgi-scriptcgi
??????? DirectoryIndexgitweb.cgi
</Directory>
</VirtualHost>
$ apt-get install python-setuptools
Next, you clone and install Gitosis from the project's mainsite:
$ git clone git://eagain.net/gitosis.git
$ cd gitosis
$ sudo python setup.py install
That installs a couple ofexecutables that Gitosis will use. Next, Gitosis wants to put its repositoriesunder /home/git?. But if you have already set up yourrepositories in /opt/git, so instead of reconfiguring everything, you create asymlink:
$ ln -s /opt/git /home/git/repositories
$ sudo -H -u git gitosis-init < /tmp/id_dsa.pub
Initialized empty Git repository in /opt/git/gitosis-admin.git/
Reinitialized existing Git repository in /opt/git/gitosis-admin.git/
This lets the user with that key modify the main Gitrepository that controls the Gitosis setup.
Next, you have to manually set the execute bit on thepost-update script for your new control repository.
$ sudo chmod 755 /opt/git/gitosis-admin.git/hooks/post-update
[gitosis]
?
[group gitosis-admin]
writable = gitosis-admin
members = scott
That means user scott has write access to repo gitosis-admin.You can add a group of access:
[group mobile]
writable = iphone_project
members = scott
Whenever you make changes to the gitosis-admin project,you have to commit the changes and push them back up to the server in order forthem to take effect. You can make your first push to the new iphone_projectproject:
$ git remote add origin git@gitserver:iphone_project.git
$ git push origin master
You no longer have to manually create a bare repository fornew projects on the server—Gitosis creates them automatically when it sees thefirst push.
[group mobile]
writable = iphone_project
members = scott josie Jessica
?
[group mobile_ro]
readable = iphone_project
members = John
git daemon --reuseaddr --base-path=/opt/git/ /opt/git/
--reuseaddr?allows the server to restart withoutwaiting for old connections to time out, the --base-path?option allows people to clone projects without specifying theentire path, and the path at the end tells the Git daemon where to look forrepositories to export.
?
[repo iphone_project]
daemon = yes
If you decide not to use Gitosis, but you want to set up aGit daemon, you have to run this on each project you want the Git daemon toserve:
$ cd /path/to/project.git
$ touch git-daemon-export-ok
The presence of that file tells Gitthat it's OK to serve this project without authentication.
$projects_list = "/home/git/gitosis/projects.list";
$projectroot = "/home/git/repositories";
$export_ok = "git-daemon-export-ok";
@git_base_url_list = ('git://gitserver');
If you want the iphone project to show up on GitWeb, youmake the repo setting look like this:
[repo iphone_project]
daemon = yes
gitweb = yes