Gitで速くcloneする方法の計測・比較

## お客様の Git repository が絶望的に遅いです

いま PM している案件で、お客様のテストサーバへの Deploy をやっているんですが、お客様の repository が絶望的に遅いです。clone するだけで10分とか。ネットワークが不安定だと…。やってられない。おめー、いい加減 timeout しろよと突っ込みたくなる。

お客様の Repository に対して、与えられている権限が限定的なので、できるところから、ということで client 側でできる clone というか読み込みを速くする方法を検証してみた。

### 方針

1. shallow-clone する
1. pull は read-only, push は ssh
1. ssh ではなく https でやる
1. さらに ssh_config をいじる

### 比較方法

github の最も Star の多いリポジトリ（[freeCodeCamp/freeCodeCamp](https://github.com/freeCodeCamp/freeCodeCamp)）を各種方法で clone し、かかった時間と転送速度（トータルの）の平均を比較する。

## Repository の状態

```
$ git branch --remote | wc -l
47
$ git rev-list --all --count
26515
```

## Git のバージョン

```
$ git --version
git version 2.28.0
```

## shallow-clone

```
$ git clone --branch master --single-branch --depth 1 git@github.com:freeCodeCamp/freeCodeCamp.git
```


clone する時のオプションでなんとかしようという話。あちこち調べると、```--single-branch``` オプションと ```--depth N```オプションがよく見られたので、それを試みる。depth は今回は1にした。

```--branch {branch name}``` でブランチ名も指定する。

```--single-branch``` はブランチの数が多い時、```--depth``` はコミット数が多い時に有効そうな気がする。そもそもの転送量を変えようというオプション（だと思う）なので、単純に効きそうである。

なのだ、が！

|option|objects|size|
|:--|:-:|:-:|
|--branch master|267,868|147.27MB|
|--branch master --single-branch|267,868|147.27MB|
|--branch master --single-branch --depth 1|5,598|8.91MB|

```--single-branch``` オプションを付けても転送量が変わらない！この後、実際に測っていくのだが、当然の如く、結果はほとんど変わらない。```--branch``` オプションを外しても同じ。
```--depth``` オプションは、説明をよく読むと、何も指定しなければ ```--single-branch``` になるそうなので、併用する意味はないが、今回は残しておく。

計測結果は、ブランチ指定しただけのものと、```--depth``` オプション付けたものを比較する。```--single-branch``` オプションだけを付けた結果は、ブランチ指定したものと同じだと思って頂ければ。


## Read-only で clone する

```
$ git clone git://github.com/freeCodeCamp/freeCodeCamp.git
```

read-only というか、git プロトコルで clone した結果、read-only になってる。（本当になってる？）

pull は Read-only, push は ssh は、

> [GitHub で clone するときは SSH じゃなく HTTP を使ったほうが高速](http://tech.nitoyon.com/ja/blog/2013/01/11/github-clone-http/)

のコメント欄参照。pushInsteadOf ってやつ。

## https でやる

```
$ git clone https://github.com/freeCodeCamp/freeCodeCamp.git
```

そのまんま。特にひねりなし。いちおう、Github の推奨方法。


## ssh_config をいじる

```config:.ssh/config
Host github.com
  Compression yes
```

のような設定をする。Ciphers は速度との関係がよく分からず、いくつか試してみたが、やっぱり速度との関係が分からないので、今回はなしで。


## 計測結果

|protocol|option|conpression|Objects|Repository size(MB)|Transfer Time(sec)|Transfer Speed(MB/sec)|
|:-:|:--|:-:|:-:|:-:|:-:|:-:|
|ssh|--branch master|no|267,868|147.27|43.33|3.76|
|ssh|--branch master --single-branch --depth 1|no|5,598|8.91|9.28|0.96|
|ssh|--branch master|yes|267,868|147.27|41.89|3.52|
|ssh|--branch master --single-branch --depth 1|yes|5,598|8.91|8.86|1.01|
|git|--branch master|-|267,868|147.27|37.09|3.97|
|git|--branch master --single-branch --depth 1|-|5,598|8.91|8.16|1.09|
|https|--branch master|-|267,868|147.27|39.13|3.76|
|https|--branch master --single-branch --depth 1|-|5,598|8.91|10.11|0.88|

予想通りの結果となりました。受信するサイズが減ると速度落ちちゃうのなんでなんだろ。

## 検証結果から見る効果

- オプションの違いでは、```--depth 1``` >> なし (すごく効果が出る可能性がある)
- プロトコルの違いでは、git > https > ssh (ぼちぼち効果あり)
- 圧縮の違いでは、あり > なし (ほとんど効果なし)

```--depth 1``` というのも限定的な使い方なのかな？と思うと、git の clone/fetch/pull を劇的に改善する方法はない。のかな。塵積もればでしょうか。


## 結論

計測しなくても分かってたようなことだったが、実際に計測・比較してみて、それぞれが、どれくらい効くのか？というのが分かった。今回検証に用いたリポジトリだけでなく、私個人の小さなリポジトリでも、ほぼ同様の傾向が見られらた。


で、絶望的に遅いお客様の Git Repository は、速くなったのか？


…

なりませんでした。私の QOL はむしろ下がったよね。
github でも bitbucket でもないお客様の git サーバがヨーロッパ（のどこかに）あって、物理的に遠いから？？20分かかる時と、4分くらいで終わる時があるのは、なんでなんだろうなー。


もっと良い方法あるよとか、やり方間違ってるよとか、うちのリポジトリだとこうだよとか、そういうのがあれば教えて下さい。