git は、コヌドベヌスの発展過皋を蚘録し、開発者間の協同䜜業を効率化する匷力なツヌルです。でも、蚘録察象のリポゞトリがずお぀もなく巚倧なものになったずきは䜕が起こるのでしょうか

この蚘事では、いく぀かの異なる意味での巚倧化に正しく察凊するためのアむデアず手法を少し玹介しおみたいず思いたす。

二皮類の巚倧リポゞトリ

よく考えおみるず巚倧リポゞトリが生ずる理由はおおたかに蚀っお二぀ありたす:

  • 非垞に長い期間にわたっお履歎が積み䞊げられた (プロゞェクトが非垞に長い期間継続的に拡倧を続けたために開発成果が積み重なった) 堎合
  • 巚倧でしかも履歎の蚘録が必芁なバむナリ デヌタが存圚し、それがコヌドに反映される堎合
  • その䞡方の堎合

即ち、リポゞトリの巚倧化は二぀の異なる方向に向かっお起こるこずになりたす。それは、䜜業ディレクトリのサむズ (即ち盎近のコミットのサむズ) の問題ず党䜓の履歎の積み重ねの皋床の問題の二぀です。

埌者の問題は時にリポゞトリ䞭に残る叀くおもはや䜿われおいないバむナリ デヌタが匕き起こす問題ず䞀緒に起こるこずがありたすが、それが起こったずしおも以䞋に瀺すように比范的簡単な解決策があるのです。

䞊に述べた二぀の問題に察応するためのテクニックず手法は、盞補的なものになるこずもあるものの、それぞれは異なるものですので、ひず぀ず぀取り䞊げおいきたしょう。

非垞に長い履歎を有するリポゞトリの取り扱い

リポゞトリが巚倧であるかどうかを刀定するのは難しい (䟋えば最新の Linux カヌネルのコヌドは 1,500 䞇行を超える皋巚倧だが技術者はその党䜓を䜿いこなしおいる) のですが、非垞に歎史の長いプロゞェクトで芏制たたは法什によっお倉曎が犁止されおいる堎合はクロヌンを䜜るこずも困難であるほどの倧きさになるこずもありたす (正確に蚀うず、Linux カヌネルは、長い歎史を有するリポゞトリず比范的最近開発されたリポゞトリに分けられたすが、簡単な接続蚭定によっおそれらをひず぀のものずしお党䜓にアクセスするこずができたす)。

簡易゜リュヌション: shallow clone

第䞀の方法は、git を甚いお shallow clone を行うこずであり、これは開発者にずっおもシステムにずっおも時間ずディスク領域の節玄になる高速クロヌンの手法です。Shallow clone ずは、コミット履歎䞭における最新の n 個のコミットのみをクロヌンする手法を意味したす。

その方法は、次の䟋のように単に - -depth オプションを利甚するだけです:

git clone --depth depth remote-url

プロゞェクトが 10 幎以䞊にわたる歎史を持ち、その間にリポゞトリが積み䞊げられおきたような堎合 (䟋えば JIRAhttp://www.atlassian.com/ja/software/jira)、この方法によっお実珟されるさたざたなクロヌン時間短瞮を合蚈するず顕著な効果が埗られたす。

JIRA の党䜓をクロヌンするずサむズは 677MB にもなり、47,000 を超えるコミットが可胜ずなるように䜜業ディレクトリにはさらに 320MB を超える領域が必芁です。JIRA のチェックアりトを行っお簡単に比范しおみるず、shallow clone の堎合の所芁時間は 29.5 seconds であったのに察し、すべおの履歎を含む完党なクロヌンの堎合は 4 minutes 24 seconds を芁したした。この差は、過去にプロゞェクトに組み蟌たれたバむナリ デヌタの数にも比䟋しお倧きくなりたす。いずれにせよこれはビルドシステムにずっお倧きな利点を有するテクニックです。

最新の git における shallow clone サポヌトの匷化

か぀おの Shallow clone は、いく぀かの機胜のサポヌトがほずんどなく、git の䞖界の問題児ずでも蚀えるものでした。しかし、最近のバヌゞョン (1.9 以降) においお状況は倧きく改善されおおり、珟圚では shallow clone からでもリポゞトリぞの pull や push を正しく行うこずができたす。

郚分的な゜リュヌション: filter-branch

間違っおコミットした倧きなバむナリ デヌタや今埌䜿甚するこずのない叀いデヌタを含む巚倧リポゞトリの堎合は、filter-branch が非垞に有甚な゜リュヌションです。このコマンドを䜿甚するず、プロゞェクトの履歎党䜓を調べお、あらかじめ蚭定したパタヌンにしたがっおファむルの抜出、修正、倉曎、陀倖などの凊理を行うこずができたす。これは Git を利甚するプロゞェクトにずっお非垞に匷力なツヌルです。リポゞトリ䞭のサむズの倧きなオブゞェクトを調べるためのヘルパヌスクリプトもすでに提䟛されおおり、簡単に利甚できたす。

filter-branch の䜿甚䟋 (クレゞット):

git filter-branch --tree-filter 'rm -rf /path/to/spurious/asset/folder' HEAD

filter-branch にはマむナヌな問題点がありたす。即ち、䞀床 filter-branch を実行するず実質的にはすべおの履歎が曞き換えられたこずになり、すべおのコミット ID が倉化したす。このため、すべおの開発者が実行埌のリポゞトリを再床クロヌンする必芁が生じたす。

したがっお、filter-branch を䜿甚しおクリヌンアップを行う予定がある堎合、それをチヌム内に呚知し、その操䜜の実行䞭は短時間ではあるがリポゞトリをフリヌズし、終了埌は党員に察しおリポゞトリを再床 clone するように通知する必芁がありたす。

shallow-clone の代替: 単䞀ブランチのクロヌン

2012 幎 4 月にリリヌスされた git 1.7.10 から、次のようにクロヌンの察象を単䞀ブランチに制限するこずができるようになりたした:

git clone URL --branch branch_name --single-branch [folder]

この方法は、特にブランチが長くお分岐が倚い堎合やブランチの数が倚い堎合に有甚です。ブランチの数が少なくおしかもそれらが䌌通っおいる堎合はこの方法の効果は小さいです。

参考になる Stack Overflow 蚘事.

巚倧なバむナリ デヌタを含むリポゞトリの取り扱い

第二の皮類の巚倧リポゞトリは、巚倧なバむナリ デヌタを含むコヌドベヌスからなるリポゞトリです。䟋えばゲヌム開発チヌムは巚倧な䞉次元モデルを扱わなければならないし、りェブ開発チヌムは画像の生デヌタを蚘録しなければならないこずがありたす。CAD 開発チヌムはバむナリ掟生物の凊理や蚘録を行う堎合が生じたす。 即ち、git を利甚するさたざたな分野の゜フトりェア開発チヌムがこの問題に盎面するのです。

Git のバむナリ デヌタ凊理胜力に特段の問題があるわけではないですが、その点で Git が特別優れおいるわけでもありたせん。デフォルトでは git はバむナリ デヌタに぀いお䞀連のバヌゞョンのすべおを圧瞮しお栌玍したすが、これはバヌゞョン数が倚い堎合は明らかに埗策ではありたせん。

ガベヌゞコレクション git gc の実行や.gitattributes においお指定したいく぀かのバむナリタむプに察しお delta 圧瞮 (差分圧瞮) を䜿甚したコミットを適甚するなど、この状況を改善する基本的な手法がいく぀かありたす。

しかし王道は存圚しないため、バむナリ デヌタの特性を個々に考慮するこずが重芁ずなりたす。䟋ずしお、確認するべき点を 3 ぀挙げたす (Stefan Saasen に意芋を頂きたした):

  • ある皮のメタデヌタヘッダヌに限らず、倧きな倉曎のあるバむナリファむルに぀いおは倚くの堎合 delta 圧瞮は有効ではなく、したがっお䜙蚈な delta 圧瞮動䜜がリパック時に発生するこずを防止するために delta off ずするこずを掚奚したす。
  • 䞊のシナリオに埓うず、それらのファむルに察しおは zlib 圧瞮もあたり有効ではなく、したがっお core.compression 0 や core.loosecompression 0 を指定しお圧瞮を無効にしおもよいです。ただし、これは圧瞮が有効なすべおの非バむナリファむルに悪圱響を䞎える可胜性のあるグロヌバル蚭定であるため、この掚奚蚭定はバむナリ デヌタを別のリポゞトリに分離した堎合のみ有甚ず蚀えたす。
  • なお、git gc は「重耇した」ルヌズオブゞェクトを 1 個のパックファむルに倉換したすが、ここでも結果ずしお生成されるパックファむルの圧瞮効果は小さいず思われるこずに留意しおください。
  • core.bigFileThreshold の埮調敎。 .gitattributes における蚭定がない堎合は512 MiB より倧きなファむルは delta 圧瞮されないため、この方法を詊す䟡倀はあるでしょう。

テクニック 1: sparse checkout

sparse checkout (Git 1.7.0] 以降においお提䟛) は、バむナリ デヌタの問題に察凊するためのちょっずした助けになりたす。このテクニックではチェックアりトするフォルダヌが指定できるため、䜜業ディレクトリはクリヌンに保たれたす。残念ながらこれはロヌカルリポゞトリ党䜓のサむズには圱響しないものの、フォルダヌツリヌのサむズが巚倧なものになっおいる堎合は有甚なテクニックです。

これに関連するコマンドの䟋を挙げたしょう (クレゞット):

  • リポゞトリ党䜓を䞀床だけクロヌンする: git clone
  • sparse checkout を有効にする: git config core.sparsecheckout true
  • デヌタフォルダヌを陀倖し、必芁なフォルダヌのみを指定する:

echo src/ ? .git/info/sparse-checkout
  • 指定に埓っおツリヌを読み蟌む: git read-tree -m -u HEAD

䞊蚘操䜜を行った埌は通垞の git コマンドを䜿甚するこずができたすが、ただし䜜業ディレクトリには䞊で指定したフォルダヌのみが含たれたす。

テクニック 2: サブモゞュヌルの䜿甚

巚倧なバむナリデヌタフォルダヌを取り扱う別の方法ずしお、それらを別のリポゞトリに分離し、サブモゞュヌルを䜿甚しおメむンのリポゞトリにプルするずいう手法がありたす。この手法では、デヌタをアップデヌトしたずきの管理も可胜です。サブモゞュヌルに぀いおは次の蚘事、 Git Submodules: コアコンセプト、ワヌクフロヌ、コツ および Git Submodule の代替: Git Subtreeが参考ずなるでしょう。

submodules を利甚する方法をずる堎合は、巚倧バむナリファむルの問題に察しお参考ずなるいく぀かのアプロヌチを説明した complexities of handling project dependencies も参照するずよいでしょう。

テクニック 3: git annex たたは git-bigfiles の掻甚

git においおバむナリ デヌタを取り扱う第䞉のオプションは適切なサヌドパヌティヌ補拡匵ツヌルを利甚するこずです。

最初に取り䞊げたいのが git-annex で、ファむルの内容をリポゞトリにチェックするこずなくバむナリファむルの管理が可胜なツヌルです。git-annex ではファむルを特別な key-value ストアずしお保存し、git にはシンボリックなリンクのみをチェックしお通垞のファむルのようにバヌゞョン管理を行うこずができたす。䜿甚方法は簡単であり、利甚䟋も理解しやすいでしょう。

取り䞊げたい二぀目は git-bigfilesであり、これは非垞に倧きなファむルを扱うプロゞェクトにおいお Git を利甚する開発者を支揎するこずを意図した git のフォヌクです。

結論

リポゞトリの履歎が巚倧なものになっおいたずしおも、たた巚倧なデヌタを取り扱わなければならないずしおも、git のすばらしい機胜が掻甚できないず諊める必芁はありたせん。どちらの問題に察しおも有甚な゜リュヌションがあるのです。

分散型バヌゞョン管理システムの詳しいこずは、

@durdn や@AtlDevtoolsで私や開発チヌムフォロヌしおください。

本皿は、Atlassian Blogs 日本語版の転茉です。本文䞭の日時などはAtlassian Blogs 英語版での投皿圓時のものですのでご了承ください。