Git
Chapters ▾ 2nd Edition

4.1 Gitサーバー - プロトコル

ここまで読んだみなさんは、ふだん Git を使う上で必要になるタスクのほとんどを身につけたことでしょう。 しかし、Git で何らかの共同作業をしようと思えばリモートの Git リポジトリを持つ必要があります。 個人リポジトリとの間でのプッシュやプルも技術的には可能ですが、お勧めしません。よっぽど気をつけておかないと、ほかの人がどんな作業をしているのかをすぐに見失ってしまうからです。 さらに、自分のコンピューターがオフラインのときにもほかの人が自分のリポジトリにアクセスできるようにしたいとなると、共有リポジトリを持つほうがずっと便利です。 というわけで、他のメンバーとの共同作業をするときには、中間リポジトリをどこかに用意してみんながそこにアクセスできるようにし、プッシュやプルを行うようにすることをお勧めします。

Git サーバーを立ち上げるのは単純です。 まず、サーバーとの通信にどのプロトコルを使うのかを選択します。 この章の最初のセクションで、どんなプロトコルが使えるのかとそれぞれのプロトコルの利点・欠点を説明します。 その次のセクションでは、それぞれのプロトコルを使用したサーバーの設定方法とその動かし方を説明します。 最後に、ホスティングサービスについて紹介します。他人のサーバー上にコードを置くのが気にならない、そしてサーバーの設定だの保守だのといった面倒なことはやりたくないという人のためのものです。

自前でサーバーを立てることには興味がないという人は、この章は最後のセクションまで読み飛ばし、ホスティングサービスに関する情報だけを読めばよいでしょう。そして次の章に進み、分散ソース管理環境での作業について学びます。

リモートリポジトリは、一般的に ベア(bare)リポジトリ となります。これは、作業ディレクトリをもたない Git リポジトリのことです。 このリポジトリは共同作業の中継地点としてのみ用いられるので、ディスク上にスナップショットをチェックアウトする必要はありません。単に Git のデータがあればそれでよいのです。 端的に言うと、ベアリポジトリとはそのプロジェクトの .git ディレクトリだけで構成されるもののことです。

プロトコル

Git では、データ転送用のプロトコルとして Local、HTTP、Secure Shell (SSH)、Git の四つを使用できます。 ここでは、それぞれがどんなものなのかとどんな場面で使うべきか (使うべきでないか) を説明します。

Local プロトコル

一番基本的なプロトコルが Local プロトコル です。これは、リモートリポジトリをディスク上の別のディレクトリに置くものです。 これがよく使われるのは、たとえばチーム全員がアクセスできる共有ファイルシステム (NFS など) がある場合です。あるいは、あまりないでしょうが全員が同じコンピューターにログインしている場合にも使えます。 後者のパターンはあまりお勧めできません。すべてのコードリポジトリが同じコンピューター上に存在することになるので、何か事故が起こったときに何もかも失ってしまう可能性があります。

共有ファイルシステムをマウントしているのなら、それをローカルのファイルベースのリポジトリにクローンしたりお互いの間でプッシュやプルをしたりすることができます。 この手のリポジトリをクローンしたり既存のプロジェクトのリモートとして追加したりするには、リポジトリへのパスを URL に指定します。 たとえば、ローカルリポジトリにクローンするにはこのようなコマンドを実行します。

$ git clone /opt/git/project.git

あるいは次のようにすることもできます。

$ git clone file:///opt/git/project.git

URL の先頭に file:// を明示するかどうかで、Git の動きは微妙に異なります。 file:// を明示せずパスだけを指定した場合、Git は必要なオブジェクトにハードリンクを張るか、そのままコピーしようとします。 一方 file:// を指定した場合は、Git がプロセスを立ち上げ、そのプロセスが (通常は) ネットワーク越しにデータを転送します。一般的に、直接のコピーに比べてこれは非常に非効率的です。 file:// プレフィックスをつける最も大きな理由は、関係のない参照やオブジェクト(他のバージョン管理システムからインポートしたときなどにあらわれることが多いです。詳細は Gitの内側 を参照してください) を除いたクリーンなコピーがほしいということです。 本書では通常のパス表記を使用します。そのほうがたいていの場合に高速となるからです。

ローカルのリポジトリを既存の Git プロジェクトに追加するには、このようなコマンドを実行します。

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

そうすれば、このリモートとの間のプッシュやプルを、まるでネットワーク越しにあるのと同じようにすることができます。

利点

ファイルベースのリポジトリの利点は、シンプルであることと既存のファイルアクセス権やネットワークアクセスを流用できることです。 チーム全員がアクセスできる共有ファイルシステムがすでに存在するのなら、リポジトリを用意するのは非常に簡単です。 ベアリポジトリのコピーをみんながアクセスできるどこかの場所に置き、読み書き可能な権限を与えるという、ごく普通の共有ディレクトリ上での作業です。 この作業のために必要なベアリポジトリをエクスポートする方法については サーバー用の Git の取得 で説明します。

もうひとつ、ほかの誰かの作業ディレクトリの内容をすばやく取り込めるのも便利なところです。 同僚と作業しているプロジェクトで相手があなたに作業内容を確認してほしい言ってきたときなど、わざわざリモートのサーバーにプッシュしてもらってそれをプルするよりは単に git pull /home/john/project のようなコマンドを実行するほうがずっと簡単です。

欠点

この方式の欠点は、メンバーが別の場所にいるときに共有アクセスを設定するのは一般的に難しいということです。 自宅にいるときに自分のラップトップからプッシュしようとしたら、リモートディスクをマウントする必要があります。これはネットワーク越しのアクセスに比べて困難で遅くなるでしょう。

また、何らかの共有マウントを使用している場合は、必ずしもこの方式が最高速となるわけではありません。 ローカルリポジトリが高速だというのは、単にデータに高速にアクセスできるからというだけの理由です。 NFS 上に置いたリポジトリは、同じサーバーで稼動しているリポジトリに SSH でアクセスしたときよりも遅くなりがちです。SSH でアクセスしたときは、各システムのローカルディスクにアクセスすることになるからです。

もう1点、このプロトコルは「不慮の事故」を防ぐようにはできていない点も注意しておきましょう。 全ユーザーが接続先のディレクトリにシェルで自由にアクセスできるようになるため、Git 内部ファイルの変更・削除を防止することができないからです。仮にそういったことが起こると、リポジトリが破損してしまいます。

HTTPプロトコル

HTTP を使って Git でやりとりをする場合、2つのモードが使えます。 以前のバージョンでは、単純で読み取り専用のモードしかありませんでした。 しかしバージョン 1.6.6 でより高機能なプロトコルが導入されました。これは、SSH の場合と同じように、HTTP でのデータのやりとりも Git が賢く処理できるようにするためのものでした。 ここ数年で、新しいほうの HTTP プロトコル はとても多く使われるようになりました。ユーザーからすればこちらのほうがシンプルですし、通信方法としても優れているからです。 新しいほうは “smart” HTTP プロトコルと呼ばれていて、古いほうは「ダム」(dumb)HTTP プロトコルと呼ばれています。 まずは “smart” HTTP プロトコルのほうから説明しましょう。

Smart HTTP

“smart” HTTP プロトコルの動きは SSH や Git プロトコルと似ていますが、HTTP/S の標準ポートを使って通信します。また、HTTP 認証の仕組みをいくつも使うことができます。 よって、ユーザーにとっては SSH などよりも簡単であることが多いです。というのも、ユーザー名とパスワードを使ったベーシック認証を、SSH 鍵認証の代わりに使えるからです。

いまでは、Git で一番使われているのがこの方法だと思います。 というのも、 git:// プロトコルが提供する匿名での読み込み機能と、SSH プロトコルが提供する認証・暗号化を経た書き込み機能の両方が、これひとつで実現できるからです。 これまでこういったことをするにはそれぞれに URL を用意する必要がありました。 いまでは、ひとつの URL で双方を実現できます。 プッシュしようとしたリポジトリで認証が必要であれば(通常であればそうすべきです)、サーバーはユーザー名とパスワードを要求することができます。 また、同じことが、読み込みについても言えます。

実際のところ、GitHub のようなサービスの場合、ブラウザでリポジトリを見るときに使う URL ( “https://github.com/schacon/simplegit” など)と同じものを使って、リポジトリをクローンすることができます。書き込み権限があるなら、プッシュする場合も同じ URL が使えます。

Dumb HTTP

Git の smart HTTP プロトコルにサーバーが応答しない場合、Git クライアントは簡易な “dumb” HTTP プロトコルへフォールバックします。 Dumb プロトコルでは、Git のベアリポジトリが通常のファイルと同じように ウェブサーバーから配信されます。 これのいいところは、セットアップがとても簡単な点です。 ベースとして必要になるのは、ベアリポジトリを HTTP ドキュメントのルートに配置することと、特定の post-update フックを設定することだけです(詳しくは Git フック を参照)。 それができれば、リポジトリを配置したサーバーにアクセスできる人なら誰でも、そのリポジトリをクローンできます。 HTTP を使ったリポジトリへのアクセスは、以下のようにすると許可できます。

$ 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

これだけです。 Git に標準でついてくる post-update フックは、適切なコマンド (git update-server-info) を実行して HTTP でのフェッチとクローンをうまく動くようにします。 このコマンドが実行されるのは、このリポジトリに対して SSH 越しでのプッシュがあったときです。その他の人たちがクローンする際には次のようにします。

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

今回の例ではたまたま /var/www/htdocs (一般的な Apache の標準設定) を使用しましたが、別にそれに限らず任意のウェブサーバーを使うことができます。 単にベアリポジトリをそのパスに置けばよいだけです。 Git のデータは、普通の静的ファイルとして扱われます (実際のところどのようになっているかの詳細は Gitの内側 を参照ください)。

なお、構築するサーバーを選択する際は、読み書きが可能な Smart HTTP か、読み込み専用でファイルを配信する Dumb HTTP かのいずれかのサーバーを選ぶことになるでしょう。両方を混ぜあわせたものを構築することはめったにありません。

利点

ここでは、Smart HTTP プロトコルに限った範囲で利点について説明します。

ひとつの URL で全アクセスを処理できること、サーバーが入力を求めてくるのは認証が必要なときだけ、という2点があれば、エンドユーザーは Git をとても簡単に使えるようになります。 また、ユーザー名とパスワードを使って認証を受けられるのも、SSH と比べた場合大きな利点です。それができれば、SSH 鍵を生成したり公開鍵をサーバーへアップロードしなくても、サーバーとやりとりできるからです。 中~上級者以外、または SSH があまり使われていないシステムのユーザーにとって、これはユーザビリティの点で大きな利点になります。 それに、HTTP プロトコルは SSH のようにとても早くて効率もよいです。

HTTPS で読み込み専用のリポジトリを公開することもできます。 これで、転送されるコンテンツを暗号化したりクライアント側で特定の署名つき SSL 証明書を使わせたりすることができるようになります。

もうひとつの利点としてあげられるのは、HTTP が非常に一般的なプロトコルであるということです。たいていの企業のファイアウォールはこのポートを通すように設定されています。

欠点

HTTP/S で Git を使えるようサーバーを設定するのは、SSH とは違ってやっかいなケースがあります。 それを除けば、他のプロトコルが “Smart” HTTP プロトコルより Git 用として優れてる点はほとんどありません。

上述のやっかいなケースとは、HTTP を認証が必要なプッシュに用いるケースです。その場合、認証情報を入力するのは SSH 鍵を用いるより複雑になりがちです。 とはいえ、認証情報をキャッシュしてくれるツール(OSX の Keychain や Windows の資格情報マネージャーなど)を使えば、それも問題ではなくなります。認証情報の保存 を読めば、HTTP パスワードキャッシュを各システムで有効にする方法がわかるでしょう。

SSH プロトコル

Git サーバーを自分でホスティングしているなら、転送プロトコルのうち一般的なのは SSH です。 SSH によるサーバーへのアクセスは、ほとんどの場面で既に用意されているからです。仮にまだ用意されていなかったとしても、導入するのは容易なことです。 SSH は認証付きのネットワークプロトコルでもあります。あらゆるところで用いられているので、環境を準備するのも容易です。

Git リポジトリを SSH 越しにクローンするには、次のように ssh:// URL を指定します。

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

あるいは、SCPコマンドのような省略形を使うこともできます。

$ git clone user@server:project.git

ユーザー名も省略することもできます。その場合、Git は現在ログインしているユーザーでの接続を試みます。

利点

SSH を使う利点は多数あります。 まず、一般的に SSH 環境の準備は容易です。SSH デーモンはごくありふれたツールなので、ネットワーク管理者の多くはその使用経験があります。また、多くの OS に標準で組み込まれており、管理用ツールが付属しているものもあります。 さらに、SSH 越しのアクセスは安全です。すべての転送データは暗号化され、信頼できるものとなります。最後に、HTTP/S、Git、Local プロトコルと同程度に効率的です。転送するデータを可能な限りコンパクトにすることができます。

欠点

SSH の欠点は、リポジトリへの匿名アクセスを許可できないということです。 たとえ読み込み専用であっても、リポジトリにアクセスするには SSH 越しでのマシンへのアクセス権限が必要となります。つまり、オープンソースのプロジェクトにとっては SSH はあまりうれしくありません。 特定の企業内でのみ使用するのなら、SSH はおそらく唯一の選択肢となるでしょう。 あなたのプロジェクトに読み込み専用の匿名アクセスを許可しつつ自分は SSH を使いたい場合は、リポジトリへのプッシュ用に SSH を用意するのとは別にプル用の環境として別のプロトコルを提供する必要があります。

Git プロトコル

次は Git プロトコルです。 これは Git に標準で付属する特別なデーモンです。専用のポート (9418) をリスンし、SSH プロトコルと同様のサービスを提供しますが、認証は行いません。 Git プロトコルを提供するリポジトリを準備するには、git-daemon-export-ok というファイルを作らなければなりません (このファイルがなければデーモンはサービスを提供しません)。ただ、このままでは一切セキュリティはありません。 Git リポジトリをすべての人に開放し、クローンさせることができます。 しかし、一般に、このプロトコルでプッシュさせることはありません。 プッシュアクセスを認めることは可能です。しかし認証がないということは、その URL を知ってさえいればインターネット上の誰もがプロジェクトにプッシュできるということになります。 これはありえない話だと言っても差し支えないでしょう。

利点

Git プロトコルは、もっとも高速なネットワーク転送プロトコルであることが多いです。 公開プロジェクトで大量のトラフィックをさばいている場合、あるいは巨大なプロジェクトで読み込みアクセス時のユーザー認証が不要な場合は、Git デーモンを用いてリポジトリを公開するとよいでしょう。 このプロトコルは SSH プロトコルと同様のデータ転送メカニズムを使いますが、暗号化と認証のオーバーヘッドがないのでより高速です。

欠点

Git プロトコルの弱点は、認証の仕組みがないことです。 Git プロトコルだけでしかプロジェクトにアクセスできないという状況は、一般的に望ましくありません。 SSH や HTTP と組み合わせ、プッシュ (書き込み) 権限を持つ一部の開発者には SSH を使わせてそれ以外の人には git:// での読み込み専用アクセスを用意することになるでしょう。 また、Git プロトコルは準備するのがもっとも難しいプロトコルでもあります。 まず、独自のデーモンを起動しなければなりません。そのためには xinetd やそれに類するものの設定も必要になりますが、これはそんなにお手軽にできるものではありません。 また、ファイアウォールでポート 9418 のアクセスを許可する必要もあります。これは標準のポートではないので、企業のファイアウォールでは許可されなていないかもしれません。 大企業のファイアウォールでは、こういったよくわからないポートは普通ブロックされています。