COLOPL Tech Blog

コロプラのエンジニアブログです

Git 2.38 で追加されたScalarってなに?

Scalar とは

大規模リポジトリを対象とした、リポジトリ容量最適化・コマンド高速化のための拡張機能の提供とgit configの自動設定を行うツールです。元々 Microsoft によって開発されていました (https://github.com/microsoft/scalar) が、Git 2.38よりメインストリームに取り込まれたことで同梱されるようになりました。

github.blog

下記コマンドでScalarを利用することができます。

# 既存リポジトリでScalarを利用する場合
$ cd /path/to/repo
$ scalar register

# 新規でクローンする場合
$ scalar clone /path/to/repo 

実際に、https://github.com/git/gitリポジトリを対象にScalarを利用するとなにが起きるのか今回は調べてみました。

`scalar register` するとどうなる?

既存のリポジトリに対して scalar regsiterをすると、git configに下記が追加されます。

scalar.repo=/Users/xxx/git
maintenance.repo=/Users/xxx/git
core.multipackindex=true
core.preloadindex=true
core.untrackedcache=true
core.autocrlf=false
core.safecrlf=false
core.fsmonitor=true
am.keepcr=true
credential.https://dev.azure.com.usehttppath=true
credential.validate=false
gc.auto=0
gui.gcwarning=false
index.threads=true
index.version=4
merge.stat=false
merge.renames=true
pack.usebitmaps=false
pack.usesparse=true
receive.autogc=false
feature.manyfiles=false
feature.experimental=false
fetch.unpacklimit=1
fetch.writecommitgraph=false
fetch.showforcedupdates=false
status.aheadbehind=false
commitgraph.generationversion=1
log.excludedecoration=refs/prefetch/*
maintenance.auto=false
maintenance.strategy=incremental

主に最適化のための設定になりますが、改行コードの扱い、マージの挙動なども含まれていました。開発者によっては設定を戻す必要があるため、変更される項目については確認が必要です。

いくつか特徴的なものを上げると、

core.untrackedcache=true
core.fsmonitor=true

では、2.37で追加されたFSMonitor というデーモン型のファイル管理システムを用いたgit statusの高速化が有効化されています。
github.blog


maintenance.repo=/Users/xxx/git
maintenance.auto=false
maintenance.strategy=incremental
gc.auto=0
fetch.writecommitgraph=false

こちらは2.31に追加されたGitリポジトリの最適化をバックグランドで行う設定となっており、1時間毎にprefetch と commit-graphの生成(git statusなどの高速化)、1日毎に容量の最適化が行われるようになります。git gc や fetch でもともと行われていた最適化は止め、バックグラウンドで定期的に行うことにより高速化と最適化を両立しています。
github.blog


git maintenanceで行われるprefetchでは、ローカルのrefs/remoteは書き換えずfetchした最新情報を保持しており、次回fetch時にその情報を用いることで高速化しているようです。
prefetchされているときとされていないときのfech時間を計測してみましたが、最新までprefetchできているときは当たり前ですが待ち時間なくfetchできるようになっています。

# prefetchしない場合
$ time git fetch
remote: Enumerating objects: 324817, done.
remote: Counting objects: 100% (324817/324817), done.
remote: Compressing objects: 100% (77849/77849), done.
remote: Total 324817 (delta 244704), reused 324817 (delta 244704), pack-reused 0
Receiving objects: 100% (324817/324817), 194.56 MiB | 84.28 MiB/s, done.
Resolving deltas: 100% (244704/244704), done.
From /Users/xxx/git-bare
 * [new branch]            master     -> origin/master
git fetch  12.36s user 1.26s system 142% cpu 9.587 total

$ git show-ref 
3dcec76d9df911ed8321007b1d197c1a206dc164 refs/remotes/origin/master

# prefetchした場合
$ git show-ref
3dcec76d9df911ed8321007b1d197c1a206dc164 refs/prefetch/remotes/origin/master

$ time git fetch
From /Users/xxx/git-bare
 * [new branch]            master     -> origin/master
warning: fetch normally indicates which branches had a forced update,
but that check has been disabled; to re-enable, use '--show-forced-updates'
flag or run 'git config fetch.showForcedUpdates true'
git fetch  0.01s user 0.02s system 72% cpu 0.044 total

$ git show-ref
3dcec76d9df911ed8321007b1d197c1a206dc164 refs/prefetch/remotes/origin/master
3dcec76d9df911ed8321007b1d197c1a206dc164 refs/remotes/origin/master

`scalar clone` するとどうなる?

通常のgit clone と、scalar cloneを比べてみました。
clone時間は約4分の1、clone後の.gitディレクトリは半分近くの容量で抑えられました。

# git clone
% time git clone https://github.com/git/git.git
Cloning into 'git'...
remote: Enumerating objects: 335027, done.
remote: Total 335027 (delta 0), reused 0 (delta 0), pack-reused 335027
Receiving objects: 100% (335027/335027), 200.78 MiB | 18.12 MiB/s, done.
Resolving deltas: 100% (250551/250551), done.
git clone https://github.com/git/git.git  16.06s user 3.46s system 102% cpu 19.112 total

% du -sh git/.git    
218M    git/.git

# scalar clone
% time scalar clone https://github.com/git/git.git
Initialized empty Git repository in /Users/xxx/git/src/.git/
warning: fetch normally indicates which branches had a forced update,
but that check has been disabled; to re-enable, use '--show-forced-updates'
flag or run 'git config fetch.showForcedUpdates true'
remote: Enumerating objects: 473, done.
remote: Counting objects: 100% (411/411), done.
remote: Compressing objects: 100% (411/411), done.
remote: Total 473 (delta 1), reused 0 (delta 0), pack-reused 62
Receiving objects: 100% (473/473), 1.95 MiB | 3.78 MiB/s, done.
Resolving deltas: 100% (1/1), done.
warning: fetch normally indicates which branches had a forced update,
but that check has been disabled; to re-enable, use '--show-forced-updates'
flag or run 'git config fetch.showForcedUpdates true'
Updating files: 100% (474/474), done.
branch 'master' set up to track 'origin/master'.
Already on 'master'
Your branch is up to date with 'origin/master'.
scalar clone https://github.com/git/git.git
4.47s user 1.39s system 60% cpu 9.715 total

% du -sh git/src/.git
 92M    git/src/.git

scalar cloneのリポジトリのconfigを確認したところブロブレスクローンで行われていました。各ブロブ情報はHEAD以外に必要なタイミングで取得する方式で、容量を抑えつつgit cloneを高速化し、コミットとツリー情報はあるためgit log には影響しないのが特徴なパーシャルクローンとなります。
github.blog


またsparse-checkoutも有効となっており、特定ディレクトリのみをcloneすることができるようになっています。モノリポで管理されているリポジトリにおいて開発者が担当するソースコードだけを手元に置くなどの用途のために使われています。
github.blog


実はscalar cloneするとプロジェクトディレクトリの下にsrcディレクトリが間に挟まるような構成となっています。これまでgitignoreで定義していたビルド結果やパッケージをGitリポジトリ外に置けるようにし、Gitの監視配下から外すことで最適化しているようです。

  • repo
    • ビルド結果などをここに置く
    • src

github.com

Scalarの注意点

便利に設定してくれるScalarですが、注意点がいくつかあります。

その一つがScalar推奨の設定がGit推奨でないため、一部コマンド実行時にWarningがでるようになります。Scalarによるものなのか、オペレーションによるものなのかが分かりづらいので、今後のアップデートでScalar利用時は関連するWarningがでなくなるといいなと思いました。

また、Scalar適用前に戻そうと思った場合に scalar unregister を行うのですが、こちらが

  • git maintenance の定期実行の解除
  • scalar reconfigure でバージョン更新にあわせてconfigの更新ができないようにscalar管理下から外れる

となっており、一度変更のあった git config についてはそのまま書き換わったままとなります。そのため、まずはお試しでと思う方については.git/configのバックアップを取っておくのをおすすめします。

最後に

Gitに新たに追加されたScalarについて、情報が少なく不明な点も多かったため、簡単ではありますがまとめてみました。参考になったら幸いです。今回調べていてGitの新機能や設定で便利なものが追加されていることがわかり、もっと早く知りたかった!と思うものが多々ありました。

開発において誰もが触るツールだからこそ、楽に最適化できるScalarは活用していければと思います。今回は調査だけでしたので、実際に大規模プロジェクトで利用してみての体感やその他Gitの活用・効率化などを今後公開できればと思っています!



ColoplTechについて

コロプラでは、勉強会やブログを通じてエンジニアの方々に役立つ技術や取り組みを幅広く発信していきます。
connpassおよびTwitterで情報発信していますので、是非メンバー登録とフォローをよろしくお願いいたします。

colopl.connpass.com
twitter.com

また、コロプラではゲームや基盤開発のバックエンド・インフラエンジニアを積極採用中です!
興味を持っていただいた方はぜひお気軽にご連絡ください。

colopl.co.jp