LoginSignup
2
1

More than 1 year has passed since last update.

git daemon を利用したローカルミラー

Last updated at Posted at 2021-08-07

git daemon を利用したローカルミラー

git daemon を利用してローカル (同一 LAN 内あるいは同一マシン内) にミラーサーバーを構築する。

git-daemon を提供する docker image があるのでそれを使用する。

git daemon の docker image の使い方

ドキュメントを見ると以下のように使うと記載がある。

docker run --name git-daemon -d -p 9418:9418 -v $PWD/git:/git sdelrio/git-daemon

https://github.com/sdelrio/git-daemon/blob/master/git-daemon.sh のソースコードを見ると以下コマンドを実行するとわかる。

git daemon --verbose --enable=receive-pack --base-path=/git --export-all

docker container 内の /git 以下を公開することがわかる。

ホスト側の $PWD/git が docker container 内の /git にマッピングされるので docker run を実行するときのカレントディレクトリ以下に git フォルダを作成してその下にリポジトリを作成したらいいことがわかる。

シェルの表記

$ はキャッシュサーバーがある LINUX でのシェルを表し
> はクライアントである WINDOWS のコマンドプロンプトを表します。

準備

docker container と共有するディレクトリをホストに作成する。

$ mkdir -p git
$ cd git

Docker container の起動

$ docker run --name git-daemon -d -p 9418:9418 -v $PWD/git:/git sdelrio/git-daemon
Unable to find image 'sdelrio/git-daemon:latest' locally
latest: Pulling from sdelrio/git-daemon
128191993b8a: Pull complete
e707abd239ca: Pull complete
434fd9a92a5d: Pull complete
Digest: sha256:53f24a8ec8e9f56d953922f3ff3fda58fc605213d66cc4aa62268d1dc3e0b1ee
Status: Downloaded newer image for sdelrio/git-daemon:latest
6148cf752e9218ce10fb26c791f954bebbe8ee254d3fafa6ce299650b9574efd

リポジトリのミラー

例えば visual studio code のリポジトリをミラーする場合以下のように実行する。

~/git  $ git clone --mirror https://github.com/microsoft/vscode.git
Cloning into bare repository 'vscode.git'...
remote: Enumerating objects: 1326819, done.
remote: Counting objects: 100% (2231/2231), done.
remote: Compressing objects: 100% (1647/1647), done.
remote: Total 1326819 (delta 1099), reused 1140 (delta 493), pack-reused 1324588
Receiving objects: 100% (1326819/1326819), 543.47 MiB | 25.87 MiB/s, done.
Resolving deltas: 100% (949929/949929), done.
~/git  $ ls
vscode.git

ミラーを作成したマシンのIP を 192.168.11.19 とすると、以下のような URL で clone するとローカルから取得できる。

>git clone --mirror git://192.168.11.19/vscode.git
Cloning into bare repository 'vscode.git'...
remote: Counting objects: 1326819, done.
remote: Compressing objects: 100% (333264/333264), done.
remote: Total 1326819 (delta 949929), reused 1326819 (delta 949929) eceiving objects: 100% (1326819/1326819), 520.70 MiBReceiving objects: 100% (1326819/1326819), 543.11 MiB | 64.52 MiB/s, done.

Resolving deltas: 100% (949929/949929), done.

25.87 MiB/s → 64.52 MiB/s になった。

※ 試した環境ではインターネット接続が速いのであまりありがたみがないけど

リポジトリミラー (複数のサイトのリポジトリをミラーする場合)

前の節では、git ディレクトリ直下にミラーしたが、複数のホスト環境や fork も含めてミラーする場合はディレクトリがかぶって都合が悪い。
幸い git フォルダ以下に階層を掘ったらそのままのディレクトリ構成で公開してくれる。

以下のように clone するディレクトリを指定して clone する

$ git clone --mirror https://github.com/microsoft/vscode.git github.com/microsoft/vscode.git
Cloning into bare repository 'github.com/microsoft/vscode.git'...
remote: Enumerating objects: 1326819, done.
remote: Counting objects: 100% (2223/2223), done.
remote: Compressing objects: 100% (1652/1652), done.
remote: Total 1326819 (delta 1092), reused 1125 (delta 480), pack-reused 1324596
Receiving objects: 100% (1326819/1326819), 543.06 MiB | 26.16 MiB/s, done.
Resolving deltas: 100% (949794/949794), done.

github.com/microsoft/vscode.git というフォルダができる。

このようにすると以下でミラーを取得できる。

>git clone --mirror git://192.168.11.19/github.com/microsoft/vscode.git
Cloning into bare repository 'vscode.git'...
remote: Counting objects: 1326819, done.
remote: Compressing objects: 100% (333399/333399), done.
remote: Total 1326819 (delta 949794), reused 1326819 (delta 949794)Receiving objects: 100% (1326819/1326819), 526.06 MiB | 70.85 MiB
Receiving objects: 100% (1326819/1326819), 542.70 MiB | 61.61 MiB/s, done.
Resolving deltas: 100% (949794/949794), done.

insteadof を使った自動切換え

で紹介した insteadOf を使って以下を実行しておく。(指定の順番としては、ミラー、オリジナルの順番)

>git config --global url."git://192.168.11.19/".insteadOf https://

注意

"git://192.168.11.19/" の最後の / を忘れるとエラーになる。

単なるテキストの置き換えをするだけなので https://github.com/microsoft/vscode.git という URL があったとき https:// の部分を git://192.168.11.19/ に置き換えるだけです。

もし git config --global url."git://192.168.11.19".insteadOf https:// としていたら https://github.com/microsoft/vscode.gitgit://192.168.11.19github.com/microsoft/vscode.git に置換されてしまうのでエラーになる。

git://192.168.11.19/ とすることで https://github.com/microsoft/vscode.gitgit://192.168.11.19/github.com/microsoft/vscode.git に置換される。

insteadof を使ってミラーから clone

前の節のように insteadof を設定しておくと、以下コマンドを実行すると自動的にミラーに転送される。

>git clone --mirror https://github.com/microsoft/vscode.git
Cloning into bare repository 'vscode.git'...
remote: Counting objects: 1326819, done.
remote: Compressing objects: 100% (333399/333399), done.
remote: Total 1326819 (delta 949794), reused 1326819 (delta 949794)Receiving objects: 100% (1326819/1326819), 542.13 MiB | 55.58 MiB/s
Receiving objects: 100% (1326819/1326819), 542.70 MiB | 49.12 MiB/s, done.
Resolving deltas: 100% (949794/949794), done.

この速度差では、全然わからないですが、wireshark を起動しながら実行すると gitプロトコルでアクセスしに行っているのを確認できます。

以下のようにまだミラーを作成していない URL に対して clone しようとすると以下のようにエラーになります。

>git clone --mirror https://github.com/microsoft/terminal.git
Cloning into bare repository 'terminal.git'...
fatal: remote error: access denied or repository not exported: /github.com/microsoft/terminal.git

それでキャッシュサーバー上で以下を実行すると、

$ git clone --mirror https://github.com/microsoft/terminal.git  github.com/microsoft/terminal.git
Cloning into bare repository 'github.com/microsoft/terminal.git'...
remote: Enumerating objects: 133120, done.
remote: Counting objects: 100% (6025/6025), done.
remote: Compressing objects: 100% (1908/1908), done.
remote: Total 133120 (delta 4491), reused 5440 (delta 4002), pack-reused 127095
Receiving objects: 100% (133120/133120), 320.75 MiB | 27.22 MiB/s, done.
Resolving deltas: 100% (104775/104775), done.

以下の clone が成功するようになります。

>git clone --mirror https://github.com/microsoft/terminal.git
Cloning into bare repository 'terminal.git'...
remote: Counting objects: 133120, done.
remote: Compressing objects: 100% (25955/25955), done.
remote: Total 133120 (delta 104775), reused 133120 (delta 104775) eceiving objects: 100% (133120/133120), 301.28 MiB | 8Receiving objects: 100% (133120/133120), 320.70 MiB | 86.99 MiB/s, done.

Resolving deltas: 100% (104775/104775), done.

キャッシュサーバーにアクセスせず直接接続したい場合の設定 (例外指定)

>git config --global url."git://192.168.11.19/".insteadOf https://

というような設定をするとすべての要求がキャッシュサーバーに飛ぶようになります。

でもこれだと自分が開発に参加している(あるいはウオッチしている)リポジトリにアクセスしたい場合、古いキャッシュを参照することになって都合が悪い。
またリモートリポジトリに push する場合にミラーに push しようとするので都合が悪い。

個別の設定を行ってミラーにアクセスしないURLを設定します。。

例として、 PYTHON の最新の開発状況を知りたいのでキャッシュでは不満な場合(その必要がある人はこの記事読んでないと思うけど)、

以下のように URL をフル指定すると https:// の条件より詳細な指定になるのでこちらが優先されて、本物にアクセスします。

>git config --global url."https://github.com/python/cpython.git".insteadOf https://github.com/python/cpython.git

例えば python のアカウント全体を例外にしたい場合は以下でよい。

>git config --global url."https://github.com/python/".insteadOf https://github.com/python/

ローカルキャッシュの更新

サーバーの git ディレクトリ以下に移動して以下コマンドを実行することでキャッシュを更新します。

$ cd git
$ find -name "*.git" -type d | xargs -I{} git -C {} fetch --all

上記コマンドをスクリプト化しておいて、cron で回せば定期的に最新のリポジトリに更新できる。

解説

find コマンドで .git で終わるディレクトリを検索します。

$ find -name "*.git" -type d
./github.com/microsoft/vscode.git
./github.com/microsoft/terminal.git

git コマンドで -C オプションを指定すると指定した引数のディレクトリに移動したうえで git コマンドを実行します。

xargs コマンドでを使って入力から受け取った行に対してコマンドを実行します。

-I{} ではプレースホルダとして指定 するも文字列を指定します。
ここでは {} 指定します。

それで git コマンドのオプションで -C {} を指定すると xargs は find の結果のディレクトリを指定して git コマンドを実行します。

この例では xargs は以下のコマンドを実行することになる。

git -C ./github.com/microsoft/vscode.git fetch --all
git -C ./github.com/microsoft/terminal.git fetch --all

参考 (フォルダ階層を掘って clone する。すでにフォルダが存在していたら、fetch --all する)

function get_local_dir () {
    echo $1 | grep -oP '(?<=://)(.*)$'
}


function mirror () {
    localdir=$(get_local_dir $1)

    if [ -e "${localdir}" ]; then
        git -C ${localdir} fetch --all
    else
        git clone --mirror $1 ${localdir}
    fi
}

https://github.com/microsoft/vscode.git を clone する例

mirror https://github.com/microsoft/vscode.git
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1