gitはどのようにファイルを保存しますか?


225

私はgitを学び始めたので、Gitコミュニティブックを読み始めました。この本では、SVNとCVSはファイル間の違いを保存し、gitはすべてのファイルのスナップショットを保存すると言っています。

しかし、私はスナップショットでそれらが意味することを本当に理解していませんでした。gitは実際に各コミットのすべてのファイルのコピーを作成しますか?

PS:誰かがgitを学ぶためのより良い情報源を持っているなら、私はそれを感謝します。


20
ここだ華麗なポストにgitがどのように機能するかを詳細に説明しています。あなたが探しているのは、おそらくオブジェクトデータベースに関する§でしょう。
greg0ire 2011年

他の優れたリソースへのリンクを含む優れた記事。私はこれらを数時間楽しんでいました。
mihai 2015年

2
私はgitを完全に
Sumudu

回答:


275

Gitには、コミットごとにすべてのファイルの完全なコピーが含まれますが、Gitリポジトリに既に存在するコンテンツの場合、スナップショットは複製ではなく、単にそのコンテンツを指すだけです。
これは、同じ内容の複数のファイルが一度だけ保存されることも意味します。

したがって、スナップショットは基本的にコミットであり、ディレクトリ構造の内容を参照します。

いくつかの良い参考文献は次のとおりです。

git commitコマンドを使用してプロジェクトのスナップショットを保存するようにGitに指示すると、プロジェクトのすべてのファイルがその時点でどのように見えるかのマニフェストが基本的に記録されます

ラボ12は、以前のスナップショットを取得する方法を示しています


progit本は、スナップショットのより包括的な説明があります。

Gitと他のVCS(Subversionとその仲間を含む)の主な違いは、Gitがデータについて考える方法です。
概念的には、他のほとんどのシステムは、ファイルベースの変更のリストとして情報を格納します。これらのシステム(CVS、Subversion、Perforce、Bazaarなど)は、システムが保持する情報を一連のファイルと見なし、各ファイルに対して時間の経過とともに行われる変更を考慮します

デルタベースのVCS

Gitはそのようにデータを考えたり、保存したりしません。代わりに、Gitはそのデータをミニファイルシステムの一連のスナップショットのように考えています。
コミットするか、Gitでプロジェクトの状態を保存するたびに、基本的に、その時点ですべてのファイルがどのように見えるかの写真を撮り、そのスナップショットへの参照を保存します。
効率を上げるために、ファイルが変更されていない場合、Gitはファイルを再度保存せず、既に保存されている以前の同一のファイルへのリンクのみを保存します。
Gitはそのデータを以下のように考えています。

スナップショットベースのVCS

これは、Gitと他のほとんどすべてのVCSとの重要な違いです。これにより、Gitは他のほとんどのシステムが前の世代からコピーしたバージョン管理のほぼすべての側面を再考します。これにより、Gitは単なるVCSではなく、その上に構築された信じられないほど強力なツールを備えたミニファイルシステムのようになります。


Jan Hudecはこの重要なコメントを追加します:

これは概念レベルでは真実かつ重要ですが、ストレージレベルでは真実ではありません。
Gitはストレージにデルタを使用します
それだけでなく、他のどのシステムよりも効率的です。ファイルごとの履歴を保持しないため、デルタ圧縮を実行する場合、各blobを取得し、類似する可能性が高いいくつかのblobを選択し(以前のバージョンと他のバージョンの最も近い近似を含むヒューリスティックを使用して)、デルタを生成しようとし、最小のものを選択します。このように(多くの場合、ヒューリスティックスに依存します)、以前のものより類似している他の類似ファイルまたは古いバージョンを利用できます。「パックウィンドウ」パラメータを使用すると、パフォーマンスをデルタ圧縮品質と交換できます。デフォルト(10)は一般的にまともな結果をもたらしますが、スペースが限られている場合、またはネットワーク転送を高速化する場合git gc --aggressiveは、値250を使用します。これにより、実行速度が非常に遅くなりますが、履歴データに追加の圧縮が提供されます。


4
@JanHudec良い点。より見やすくするために、回答にコメントを含めました。
VonC 2013年

1
誰もがGitのようなストレージパターン、つまりハッシュベースの値ストアのコンピューターサイエンス用語を知っていますか?(または同様のもの)
Joannes Vermorel 2014年

34
OPの実際の質問のコンテキストでは、最初の段落は本当に誤解を招くようです。最後のパラグラフに到達するまでは、そうですね、そうです、Git 「ファイル間の差異を保存[...]します。本当に、情報にフラグが付けられ、それほど深く埋め込まれていないことを願っています。それで、少なくともあなたの答えのどこかに本当の話を含める;)
Josh O'Brien

1
@NickVolynkin素晴らしい!私はそれらの答えがより多くの聴衆を見つけていることを嬉しく思います。
VonC、2015

1
別の良い本:ボトムアップからのGit:ftp.newartisans.com/pub/git.from.bottom.up.pdf
Jonas Berlin

46

Gitは各ファイルをSHA1の下に論理的に格納します。つまり、リポジトリにまったく同じ内容の2つのファイルがある場合(またはファイルの名前を変更した場合)は、1つのコピーのみが保存されます。

ただし、これは、ファイルの小さな部分を変更してコミットすると、ファイルの別のコピーが保存されることも意味します。gitがこれを解決する方法は、パックファイルを使用することです。たまに、リポジトリからすべての「ばらばら」のファイル(実際には、ファイルだけでなく、コミット情報やディレクトリ情報も含むオブジェクト)が収集され、パックファイルに圧縮されます。パックファイルはzlibを使用して圧縮されます。また、同様のファイルもデルタ圧縮されます。

(少なくとも一部のプロトコルでは)プルまたはプッシュするときにも同じ形式が使用されるため、これらのファイルを再度圧縮する必要はありません。

この結果、非圧縮の作業コピー全体、非圧縮の最近のファイル、および圧縮された古いファイルを含むgitリポジトリは通常、比較的小さく、作業コピーのサイズの2分の1になります。これは、SVNが履歴をローカルに保存していない場合でも、同じファイルを含むSVNリポジトリよりも小さいことを意味します。


1
ああ、水銀の方がスペース効率が良い
ベン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.