Chapter 4. Git on the Server

1.  The preferred method for collaborating with someone is to set up an intermediate repository that you both have access to, and push to and pull from that. We refer to this repository as a Git server;It generally takes a tiny amount of resources to host a Git repo, so you'll rarely need to use an entire server for it. A remote repository is generally a bare repository —a Git repository that has no working directory. Because the repository is only used as a collaboration point, there is no reason to have a snapshot checked out on disk; it's just the Git data. In the simplest terms, a bare repository is the contents of your project's .git directory and nothing else.

 

2.  Git can use four major network protocols to transfer data: Local, Secure Shell (SSH), Git, and HTTP.

 

3.  The most basic protocol is the Local protocol, in which the remote repository is in another directory on disk. This is often used if everyone on your team has access to a shared filesystem such as an NFS mount.

 

4.  To clone a local repository, you can run:

$ 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 specify file://   at the beginning of the URL. If you just specify the path, Git tries to use hardlinks or directly copy the files it needs. If you specify file://   , Git fires up the processes that it normally uses to transfer data over a network, which is generally a lot less 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 references or objects left out—generally after an import from another version-control system or something similar.

 

To add a local repository to an existing Git project, you can run:

$ git remote add local_proj /opt/git/project.git

 

5.  If you and a co-worker are working on the same project and they want you to check something out, running a command like git pull /home/john/project   is often easier than them pushing to a remote server and you pulling down.

 

6.  To clone a Git repository over SSH, you can specify ssh:// URL like this:

$ git clone ssh://user@server:project.git

Or you can not specify a protocol—Git assumes SSH if you aren'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.

 

7.  The Git protocol is a special daemon that comes packaged with Git; it listens on a dedicated port (9418) that provides a service similar to the SSH protocol, but with absolutely no authentication. In order for a repository to be served over the Git protocol, you must create the git-export-daemon-ok   file—the daemon won't serve a repository without that file in it. There is generally no pushing over this protocol. You can enable push access; but given the lack of authentication, if you turn on push access, anyone on the Internet who finds your project's URL could push to your project.

 

8.  To allow read access to your repository over HTTP, do something like this:

$ 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 runs the appropriate command (git update-server-info   ) to make HTTP fetching and cloning work properly. This command is run when you push to this repository over SSH; then, other people can clone via:

$ git clone http://example.com/gitproject.git

 

9.  It's possible to make Git push over HTTP as well, although that technique isn't as widely used and requires you to set up complex WebDAV requirements.

( http://www.kernel.org/pub/software/scm/git/docs/howto/setup-git-server-over-http.txt .)

 

10.  In order to initially set up any Git server, you have to export an existing repository into a new bare repository—a repository that doesn't contain a working directory. You run the clone command with the --bare option

$ 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 minor differences 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 your Git repositories under the /opt/git   directory. You can set up your new repository by copying your bare repository over:

$ scp -r my_project.git [email protected]:/opt/git

At this point, other users who have SSH access to the same server, which has read access to the /opt/git   directory, can clone your repository by:

$ git clone [email protected]:/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.

Git automatically adds group write permissions to a repository properly if you run the git init command with the --shared option:

$ ssh [email protected]

$ cd /opt/git/my_project.git

$ git init --bare --shared

 

12.  You can give access of the SSH server to everyone by creating a single "git " user on the machine, ask every user to send you an SSH public key, and add that key to the ˜/.ssh/authorized_keys   file of your new "git " user. At that point, 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 connect as doesn't affect the commits you've recorded.

 

13.  By default, a user's SSH keys are stored in that user's ˜/.ssh directory. Under that directory, a pair of files are named something and something.pub , where the something is usually id_dsa or id_rsa . The .pub file is your public key, and the other file is your private key.

 

14.  A program called ssh-keygen , which is provided with the SSH package on Linux/Mac systems and comes with the MSysGit package on Windows can help to generate SSH keys. First it confirms where you want to save the key (.ssh/id_rsa ), and then it asks twice for a passphrase, which you can leave empty if you don't want to type a password when you use the key.

 

15.  If you've received a few public keys from your git users, you can append them to your authorized_keys file:

$ 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 by running git init with the --bare option, which initializes the repository 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 to gitserver :

$ 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 push changes 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

 

16.  Y ou can easily restrict the "git" user to only doing Git activities by setting git-shell   that comes with Git as your "git" user's login shell, then the "git" user can't have normal shell access to your server:

$ sudo vim /etc/passwd

At the bottom, you should find a line that looks something like this:

git:x:1000:1000::/home/git:/bin/sh

Replace it with something like:

git:x:1000:1000::/home/git:/usr/bin/git-shell

 

17.  To enable anonymous read access on Apache server for git repo, you first enable the hook:

$ 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, Git runs this command to update the files needed for HTTP fetching.

Next, you need to add a VirtualHost entry to your Apache configuration with the document root as the root directory of your Git projects:

<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/git directories to www-data   so your web server has read-access to the repositories, because the Apache instance running the CGI script will (by default) be running as that user:

$ chgrp -R www-data /opt/git

 

18.  Git comes with a CGI script called GitWeb that is commonly used for setting up a simple web-based visualizer. Git comes with a command to fire up a temporary instance if you have a lightweight server on your system like lighttpd or webrick. On Linux machines, lighttpd is often installed, so you may be able to get it to run by typing git instaweb   in your project directory. If you're running a Mac, Leopard comes preinstalled with Ruby, so webrick may be your best bet. To start instaweb with a non-lighttpd handler, you can run it with the --httpd option:

$ 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 normal web server. To install GitWeb manually(Some Linux distributions have a gitweb   package), you need to get the Git source code and generate the custom CGI script:

$ git clone git://git.kernel.org/pub/scm/git/git.git

$ cd git/

$ make GITWEB_PROJECTROOT="/opt/git" prefix=/usr gitweb/gitweb.cgi

$ sudo cp -Rf gitweb /var/www/

Now, you need to make Apache use CGI for that script, for which 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-script cgi

        DirectoryIndex gitweb.cgi

</Directory>

</VirtualHost>

 

19.  Gitosis is basically a set of scripts that help you manage the authorized_keys   file as well as implement some simple access controls. The interface for this tool for adding people and determining access isn't a web interface but a special Git repository. You set up the information in that project; and when you push it, Gitosis reconfigures the server based on that.

 

20.  Gitosis requires some Python tools, so first you have to install the Python setuptools package, which Ubuntu provides as python-setuptools :

$ apt-get install python-setuptools

Next, you clone and install Gitosis from the project's main site:

$ git clone git://eagain.net/gitosis.git

$ cd gitosis

$ sudo python setup.py install

That installs a couple of executables that Gitosis will use. Next, Gitosis wants to put its repositories under /home/git   . But if you have already set up your repositories in /opt/git , so instead of reconfiguring everything, you create a symlink:

$ ln -s /opt/git /home/git/repositories

 

21.  You need to remove the current authorized_keys file, re-add the keys later, and let Gitosis control the file automatically. You need to turn your shell back on for the "git" user, Gitosis will control that for you.

 

22.  You can initialize Gitosis by running the gitosis-init   command with your personal public key:

$ 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 Git repository that controls the Gitosis setup.

Next, you have to manually set the execute bit on the post-update script for your new control repository.

$ sudo chmod 755 /opt/git/gitosis-admin.git/hooks/post-update

 

23.  In repo gitosis-admin.git you have two major parts: gitosis.conf and keydir folder. The gitosis.Conf   file is the control file you use to specify users, repositories, and permissions. The keydir directory is where you store the public keys of all the users who have any sort of access to your repositories — one file per user. The name of the file in keydir will be different for you—Gitosis takes that name from the description at the end of the public key that was imported with the gitosis -init script.

 

24.   gitosis.conf looks like:

[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 for them to take effect. You can make your first push to the new iphone_project project:

$ git remote add origin git@gitserver:iphone_project.git

$ git push origin master

You no longer have to manually create a bare repository for new projects on the server—Gitosis creates them automatically when it sees the first push.

 

25.  Instead of appending the public keys of users manually to the ˜/.ssh/authorized_keys file on your server, you'll add them, one key per file, into the keydir directory. How you name the keys determines how you refer to the users in the gitosis.conf file.

 

26.  Gitosis has simple access controls as well. If you want John to have only read access to this project, you can do this instead:

[group mobile]

writable = iphone_project

members = scott josie Jessica

 

[group mobile_ro]

readable = iphone_project

members = John

 

27.  If you have any issues, it may be useful to add loglevel=DEBUG under the [gitosis]   section. If you've lost push access by pushing a messed-up configuration, you can manually fix the file on the server under /home/git/.gitosis.conf   —the file from which Gitosis reads its info. A push to the project takes the gitosis.conf file you just pushed up and sticks it there. If you edit that file manually, it remains like that until the next successful push to the gitosis-admin project.

 

28.  The Git protocol is far more efficient and thus faster than the HTTP protocol. It is a good choice for unauthenticated read-only access. To setup Git protocol on your git server:

git daemon --reuseaddr --base-path=/opt/git/ /opt/git/

--reuseaddr   allows the server to restart without waiting for old connections to time out, the --base-path   option allows people to clone projects without specifying the entire path, and the path at the end tells the Git daemon where to look for repositories to export.

 

29.  You have to tell your Gitosis server which repositories to allow unauthenticated Git server-based access to. If you add a section for each repository, you can specify the ones from which you want your Git daemon to allow reading. If you want to allow Git protocol access for your iphone project, you add this to the end of the gitosis.conf file:

[repo iphone_project]

daemon = yes

If you decide not to use Gitosis, but you want to set up a Git daemon, you have to run this on each project you want the Git daemon to serve:

$ cd /path/to/project.git

$ touch git-daemon-export-ok

The presence of that file tells Git that it's OK to serve this project without authentication.

 

30.  Gitosis can also control which projects GitWeb shows. First, you need to add something like the following to the /etc/gitweb.conf file:

$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, you make the repo setting look like this:

[repo iphone_project]

daemon = yes

gitweb = yes

 

31.  You have a huge number of hosting options to choose from, each with different advantages and disadvantages. To see an up-to-date list, check out the GitHosting page on the main Git wiki:http://git.or.cz/gitwiki/GitHosting

 

32.  GitHub is by far the largest open source Git hosting site, and it's also one of the very few that offers both public and private hosting options so you can keep your open source and private commercial code (charged) in the same place.

 

33.  GitHub is user centric which means when you host our grit project on GitHub, you won't find it at github.com/grit but instead at github.com/schacon/grit . There is no canonical version of any project, which allows a project to move from one user to another seamlessly if the first author abandons the project.

 

34.  If you want to contribute to an existing project to which you don't have push access, GitHub encourages forking the project. When you land on a project page that looks interesting and you want to hack on it a bit, you can click the "fork" button in the project header to have GitHub copy that project to your user so you can push to it.

猜你喜欢

转载自seanzhou.iteye.com/blog/1438358
今日推荐