17
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

サムザップAdvent Calendar 2022

Day 3

サイズの大きいUnityプロジェクトのGitリポジトリを効率的に扱うコツ

Last updated at Posted at 2022-12-02

本記事は サムザップ Advent Calendar 2022 の12/3の記事です。

Unityでの開発では画像や3Dモデルなど、多くのバイナリファイルを扱います。
そういったサイズの大きいリポジトリを効率的に扱うコツについて紹介したいと思います。


まずメインのリポジトリでUnityプロジェクトを管理しながら、サブモジュールでアセットを管理し、
それぞれでLFSで管理するような大きなファイルがあるような構成を想定します。

large-size-unity-project
├── Assets
│   ├── External
│   │   └── submodule # サブモジュールで参照している別リポジトリ
│   │       └── large-file.bin # LFSで管理している 32MBくらいの大きなファイル
│   ├── Scenes
│   ├── Scripts
│   ├── StreamingAssets
│   │   └── large-file.bin # LFSで管理している 32MBくらいの大きなファイル
│   ├── Plugins
│   └── Resources 
├── Packages
└── ProjectSettings

大規模なUnityプロジェクトのブランチ切り替えは、アセットインポートなどで時間がかかってしまうので、
予めプラットフォーム別や、開発するアプリのバージョン別にディレクトリを分けてクローンするのはよくあることかと思います。

これを単純に、同じリポジトリを別々にクローンすると、

$ git clone <REPO_URL> ./large-size-unity-project-a --recurse-submodules
$ git clone <REPO_URL> ./large-size-unity-project-b --recurse-submodules

当然ながらGitのオブジェクトやLFSのローカルキャッシュは全く同じものが2つ存在することになります、ストレージが勿体ないですね。

$ du -d 1 -BM .
129M    ./large-size-unity-project-a
129M    ./large-size-unity-project-b
257M    .

git worktree を利用して複数のワークツリーを作成する

git worktree を利用すれば同じローカルリポジトリから複数のワークツリーを作成することができます。
リポジトリを共有しているので、ローカルブランチ・コミットを相互に参照できる、などの効果がありますが、LFSのローカルキャッシュも共有してくれるのが大きなメリットです。

$ git clone <REPO_URL> ./large-size-unity-project-a --recurse-submodules
$ cd ./large-size-unity-project-a
$ git worktree add ../large-size-unity-project-b
$ cd ../large-size-unity-project-b
$ git submodule update --init
$ du -d 1 -BM .
161M    ./large-size-unity-project-a
65M     ./large-size-unity-project-b
225M    .

ただ残念ながら、git worktree ではサブモジュールの中身までは共有されないので、
容量の削減効果も、Assets/StreamingAssets/large-file.bin 一つ分(32MB)の削減と限定的なものになっています。

LFSローカルキャッシュの保存先を共有する

ワークツリー内のサブモジュールがそれぞれ個別にローカルキャッシュ保持しないように、
git config lfs.storage を設定して、LFSローカルキャッシュの保存先を共有させます。

# 後でLFSの保存先を指定するため、LFSファイルのダウンロードをスキップしてクローンする
$ GIT_LFS_SKIP_SMUDGE=1 git clone <REPO_URL> ./large-size-unity-project-a --recurse-submodules

# 保存先を指定してからLFSファイルをダウンロードする
$ pushd ./large-size-unity-project-a
$ git config lfs.storage C:/PATH_TO_REPO_ROOT/lfs && git lfs pull

# サブモジュールも同様に、保存先を指定してからLFSファイルをダウンロードする
$ pushd ./Assets/External/submodule
$ git config lfs.storage C:/PATH_TO_REPO_ROOT/lfs && git lfs pull
$ popd
$ git worktree add ../large-size-unity-project-b
$ popd

# ワークツリーは設定を共有しているので、サブモジュールだけ保存先を指定する
$ pushd ../large-size-unity-project-b
$ GIT_LFS_SKIP_SMUDGE=1 git submodule update --init
$ pushd ./Assets/External/submodule
$ git config lfs.storage C:/PATH_TO_REPO_ROOT/lfs && git lfs pull
$ popd
$ popd

コマンドを見ていただくと分かる通り、サブモジュールに関しては一つ一つ指定する必要があって煩雑です。

$ du -d 1 -BM .
65M     ./large-size-unity-project-a
65M     ./large-size-unity-project-b
65M     ./lfs
193M    .

しかしながら、その甲斐があってストレージ使用量をさらに抑えることが出来ました。
またキャッシュを共有しているので、サブモジュール更新時のLFSファイルのダウンロードも一度だけで済ませられることが期待できます。

.gitconfig の includeIf を使って特定ディレクトリ以下に一括で lfs.storage を設定する

とはいえ流石に手順が煩雑なので、もっと楽が出来る方法を取りたいと思います。

.gitconfigincludeIf を使えば、マッチしたディレクトリ以下に読み込まれる設定ファイルを指定することが出来ます。
これを利用して、特定ディレクトリ以下のリポジトリすべてで lfs.storage を共有するようにしてみましょう。

~/.gitconfig
[includeIf "gitdir:C:/PATH_TO_REPO_ROOT/"]
    path = C:/PATH_TO_REPO_ROOT/gitconfig
C:/PATH_TO_REPO_ROOT/gitconfig
[lfs]
    storage = C:/PATH_TO_REPO_ROOT/lfs

このように設定しておけば、サブモジュールも含む、設定したディレクトリ以下のリポジトリへ一括で lfs.storage を指定出来ます。

:warning:複数リポジトリで lfs.storage を共有する場合の注意点

参照されなくなったLFSローカルキャッシュを削除する git lfs prune コマンドですが、
これはコマンドを実行したリポジトリ基準で参照がチェックされるため、lfs.storage を共有した別のリポジトリからの参照は考慮されません。
そのため、参照が生きているファイルも誤って削除されてしまうため、このコマンドは実行しないようにしましょう。

git-lfs-config.5.ronn

Note: you should not run git lfs prune if you have different repositories sharing the same storage directory.

環境

本記事は以下の環境のもと作成しました。

$ git --version
git version 2.38.1.windows.1

$ git-lfs --version
git-lfs/3.2.0 (GitHub; windows amd64; go 1.18.2)

参考

17
7
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
17
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?