大規模なプロジェクトにて複数の Git リポジトリを扱う際はgoogle Repoを使用することがあります。 このRepoにてコードのダウンロードを高速化する方法を説明します。


Google Repo とは

大規模なプロジェクトだと、複数の Git リポジトリが必要になってきます。 そのリポジトリを1つ1つ操作するのは大変なので、大規模プロジェクトでは Repo というツールを使うことが多いと思います。

Repoは複数のGitリポジトリを効率的に扱うツールで、AOSP (Android Open Source Project)などで用いられています。 いろいろなところで使われている Repo ですが、たとえば AOSPはソースコードだけで250GBくらいあり、ダウンロードするだけでも時間がかかってしまいます。 そこで今回は Repo を使ったさいのコードのダウンロードの高速化について説明します。

ミラーリング

まず、ミラーリングによってサーバーへのアクセスを減らして高速化する方法を説明します。

ミラーリポジトリの作成

予めローカルマシン上にミラーリポジトリを作成します。 repo initするときに--mirrorを付けてください。

1
2
3
cd /path/to/mirror/
repo init --mirror -u ssh://your-manifest.git -b manifest-branch -m manifest-name
repo sync -j$(nproc) && repo forall -v -pc git fetch --all

ソースコードの取得

ソースコードの取得時は、先ほど作成したミラーを参照するようにします。 --reference を使用してください

1
2
repo init --reference=/path/to/mirror/ -u ssh://your-manifest.git -b manifest-branch -m manifest-name
repo sync

もしローカルマシンのミラーリポジトリがサーバリポジトリより古い場合でも、古いソースコードが取得されることはありません。 サーバから新しいソースコードを取得します。

ミラーリポジトリの更新

定期的にミラーリポジトリを最新に更新することで常に高速にソースコードを取得できます。 手動の場合は下記のコマンドで可能です。

1
cd /path/to/mirror/ && repo sync -j$(nproc) && repo forall -v -pc git fetch --all

これを自動化するには anacronを用います。通常のcron.dailyだと、WSLのような常時電源オンではない環境では期待通り実行されません。

cron.dailyはデフォルトでは朝の06:25にrun-parts --report /etc/cron.dailyを実行します。 そのときに電源が入っていない場合、処理は実行されません。anacronなら電源が投入されたときに自動で実行してくれます。

下記にanacronの導入例を示します。

1
2
3
4
sudo apt install anacron
sudo echo '#!/bin/sh' | sudo tee /etc/cron.daily/repo-mirror-sync
sudo echo sudo -i -u $(id -un) -- sh -c "'cd /path/to/mirror/ && /usr/local/bin/repo sync -j\$(nproc)' > /path/to/mirror/sync.log 2>&1" | sudo tee -a /etc/cron.daily/repo-mirror-sync
sudo chmod +x /etc/cron.daily/repo-mirror-sync

anacronが実行されたかどうかは /var/spool/anacron/以下にあるログファイルを確認してください。 下記のように実行した日付が表示されます。

1
2
$ cat /var/spool/anacron/cron.daily
2021015

シャロークローン

通常の Git と同様に Repo を使ってもシャロークローンができます。 シャロークローンは最新のコミットのみをダウンロードします。最新のビルドをしたいなど、過去の履歴が必要ない場合に有効です。 シャロークローンについてはGitHubの公式ブログのパーシャルクローンとシャロークローンを活用しよう に詳しい説明があります。 Repo の init 時に --depth=DEPTHにてシャロークローンができます。通常は 1 を指定しておけばよいでしょう。

1
repo init --depth=1 -u ssh://your-manifest.git -b manifest-branch -m manifest-name

もし過去の履歴が必要になった場合はアンシャローします。過去の履歴が必要なリポジトリの場所に移動して下記を実行します。

1
2
cd git-repository/
git fetch --unshallow

ジョブの並列化

ダウンロード時に -j オプションを付けると並列に実行できます。

1
repo sync -j16

利用可能な CPU の数を確認するには、nproc --allコマンドを実行します。下記のようにすると楽でしょう。

1
repo sync -j$(nproc --all)

フェッチするブランチを限定する

現在のブランチのみフェッチするようにすることでダウンロードを高速化できます。 -c オプションを使用します。

1
repo sync -c

まとめ

大規模プロジェクトを管理する Repo を使ってソースコードをダウンロードするときの高速化について説明しました。 下記の方法で高速にダウンロードできるかなと思います。Jenkins などの CI を回すさいなどに有効かと思います。