Yakstは、海外の役立つブログ記事などを人力で翻訳して公開するプロジェクトです。
4年以上前投稿 修正あり

Gitのリモート操作を5倍から50倍高速化するには

リモートからのgit pullなどの操作を、SSHのコネクション共有とリポジトリの自動ミラーを使って50倍高速化する方法。

原文
Speed Up Git (5x to 50x) - interrobeng‽ (English)
翻訳依頼者
D98ee74ffe0fafbdc83b23907dda3665
翻訳者
D98ee74ffe0fafbdc83b23907dda3665 doublemarket
原著者への翻訳報告
未報告


注意 Gitサーバとの距離によって結果はまちまちだ。timeコマンドを使った全く科学的とは言えないベンチマークでは、以下の手順を実行した後はgit pullが、GitHubとシンガポールAWSのEC2で5秒以下から0.1秒以下になった。

なぜ?

$ time git pull
Already up-to-date.

real    0m5.075s

Gitリポジトリが最新だってことを表示するだけで5秒かかるって?あり得ない。

SSHコネクションの共有と永続化

シンガポールでは、github.comへの往復時間は250msほどだ。GitのオペレーションをするたびにSSHコネクションを張るのは、たくさんのやり取りが発生してしまう。しかし、~/.ssh/configに以下の行を書けば、コネクションを保持して使いまわすことができる。

ControlMaster auto
ControlPath /tmp/%r@%h:%p
ControlPersist yes

ControlMaster auth は、1つのネットワークコネクションを複数のSSHセッションで使いまわす設定で、マスタコネクションがない場合はそれを張るようになる。

ControlPath /tmp/%r@%h:%p は、コネクションの共有のための制御ソケットへのパスを指定する。%rはリモートログインのユーザ名に、%hはターゲットのホスト名に、%pはポート番号に置き換えられる。

ControlPersist yesは、マスタコネクションをバックグラウンドで永続的に張り続けるという意味。

GitHubを自動ミラーリングするGitミラーを設定

秒単位でのGitリモート操作をするには、低レイテンシのサーバが必要だ。(物理的に一緒に働いていて、誰かが「プッシュした!」と言ったちょうどその時にgit pullできることを想像してみよう)

と言っても、あなたのサーバから自動的にGitHubへプッシュするようにすれば、GitHubの提供する色々なよい点を使い続けることはできる。GitHubを常に最新に保つ方法には、cronジョブを使ったり、複数のリモートサーバを持つといったいくつかの方法があるが、post-receiveフックを使うのが一番エレガントなやり方だと思う。

サーバ上で、GitHubのデプロイキーをセットアップする。

$ ssh-keygen -t rsa -C "your_email@example.com"
$ cat .ssh/id_rsa.pub

ターゲットにするリポジトリで、Settings → Deploy Keys → Add deploy keyを選び公開鍵を貼り付けて登録しよう。リポジトリをミラーすることができるようになる。

$ git clone --mirror git@github.com:ahbeng/example.git

プッシュすると自動的にGitHubにミラーするようにするには、hooks/post-receiveGitフックを設定する。

#!/bin/bash
nohup git push --mirror &>/dev/null &

スクリプトが終わるまで、Gitクライアントはコネクションを切らないので、単純にgit push --mirrorと書くだけだと、プッシュするたびにGitHubのレイテンシが影響してしまうので、これを設定する意味がなくなってしまう。そのため、nohupコマンドを使ってプロセスをバックグラウンドで動かし、ログアウトしても動き続けるようにしている。そして、ログアウト時にSSHが停止してしまうのを防ぐために、全ての出力を/dev/nullにリダイレクトしている。

フックを実行可能にしておこう。

$ chmod +x hooks/post-receive

これで新しいGitミラーをローカルで使えるようになった。サーバの秘密鍵をssh-agentに登録しておこう。

$ ssh-add ec2.pem

これでクローンもできる。

$ git clone user@hostname:example

あるいは、既にあるリポジトリのリモートリポジトリを変更しよう。

$ git remote set-url origin user@hostname:example

結果

Gitミラーを使うだけでgit pullは1.2秒まで短くなった。SSHコネクションの共有を合わせて使うと、

$ time git pull
Already up-to-date.

real    0m0.111s

Gitのリモート操作が0.1秒。素晴らしい。

次の記事
MySQL 5.6でスレーブをクラッシュセーフにするには
前の記事
InnoDBログシーケンス番号(LSN)を進める方法

Feed small 記事フィード