私はgitを学び始めたので、Gitコミュニティブックを読み始めました。この本では、SVNとCVSはファイル間の違いを保存し、gitはすべてのファイルのスナップショットを保存すると言っています。
しかし、私はスナップショットでそれらが意味することを本当に理解していませんでした。gitは実際に各コミットのすべてのファイルのコピーを作成しますか?
PS:誰かがgitを学ぶためのより良い情報源を持っているなら、私はそれを感謝します。
私はgitを学び始めたので、Gitコミュニティブックを読み始めました。この本では、SVNとCVSはファイル間の違いを保存し、gitはすべてのファイルのスナップショットを保存すると言っています。
しかし、私はスナップショットでそれらが意味することを本当に理解していませんでした。gitは実際に各コミットのすべてのファイルのコピーを作成しますか?
PS:誰かがgitを学ぶためのより良い情報源を持っているなら、私はそれを感謝します。
回答:
Gitには、コミットごとにすべてのファイルの完全なコピーが含まれますが、Gitリポジトリに既に存在するコンテンツの場合、スナップショットは複製ではなく、単にそのコンテンツを指すだけです。
これは、同じ内容の複数のファイルが一度だけ保存されることも意味します。
したがって、スナップショットは基本的にコミットであり、ディレクトリ構造の内容を参照します。
いくつかの良い参考文献は次のとおりです。
git commitコマンドを使用してプロジェクトのスナップショットを保存するようにGitに指示すると、プロジェクトのすべてのファイルがその時点でどのように見えるかのマニフェストが基本的に記録されます
ラボ12は、以前のスナップショットを取得する方法を示しています
progit本は、スナップショットのより包括的な説明があります。
Gitと他のVCS(Subversionとその仲間を含む)の主な違いは、Gitがデータについて考える方法です。
概念的には、他のほとんどのシステムは、ファイルベースの変更のリストとして情報を格納します。これらのシステム(CVS、Subversion、Perforce、Bazaarなど)は、システムが保持する情報を一連のファイルと見なし、各ファイルに対して時間の経過とともに行われる変更を考慮します
Gitはそのようにデータを考えたり、保存したりしません。代わりに、Gitはそのデータをミニファイルシステムの一連のスナップショットのように考えています。
コミットするか、Gitでプロジェクトの状態を保存するたびに、基本的に、その時点ですべてのファイルがどのように見えるかの写真を撮り、そのスナップショットへの参照を保存します。
効率を上げるために、ファイルが変更されていない場合、Gitはファイルを再度保存せず、既に保存されている以前の同一のファイルへのリンクのみを保存します。
Gitはそのデータを以下のように考えています。
これは、Gitと他のほとんどすべてのVCSとの重要な違いです。これにより、Gitは他のほとんどのシステムが前の世代からコピーしたバージョン管理のほぼすべての側面を再考します。これにより、Gitは単なるVCSではなく、その上に構築された信じられないほど強力なツールを備えたミニファイルシステムのようになります。
これは概念レベルでは真実かつ重要ですが、ストレージレベルでは真実ではありません。
Gitはストレージにデルタを使用します。
それだけでなく、他のどのシステムよりも効率的です。ファイルごとの履歴を保持しないため、デルタ圧縮を実行する場合、各blobを取得し、類似する可能性が高いいくつかのblobを選択し(以前のバージョンと他のバージョンの最も近い近似を含むヒューリスティックを使用して)、デルタを生成しようとし、最小のものを選択します。このように(多くの場合、ヒューリスティックスに依存します)、以前のものより類似している他の類似ファイルまたは古いバージョンを利用できます。「パックウィンドウ」パラメータを使用すると、パフォーマンスをデルタ圧縮品質と交換できます。デフォルト(10)は一般的にまともな結果をもたらしますが、スペースが限られている場合、またはネットワーク転送を高速化する場合git gc --aggressive
は、値250を使用します。これにより、実行速度が非常に遅くなりますが、履歴データに追加の圧縮が提供されます。
Gitは各ファイルをSHA1の下に論理的に格納します。つまり、リポジトリにまったく同じ内容の2つのファイルがある場合(またはファイルの名前を変更した場合)は、1つのコピーのみが保存されます。
ただし、これは、ファイルの小さな部分を変更してコミットすると、ファイルの別のコピーが保存されることも意味します。gitがこれを解決する方法は、パックファイルを使用することです。たまに、リポジトリからすべての「ばらばら」のファイル(実際には、ファイルだけでなく、コミット情報やディレクトリ情報も含むオブジェクト)が収集され、パックファイルに圧縮されます。パックファイルはzlibを使用して圧縮されます。また、同様のファイルもデルタ圧縮されます。
(少なくとも一部のプロトコルでは)プルまたはプッシュするときにも同じ形式が使用されるため、これらのファイルを再度圧縮する必要はありません。
この結果、非圧縮の作業コピー全体、非圧縮の最近のファイル、および圧縮された古いファイルを含むgitリポジトリは通常、比較的小さく、作業コピーのサイズの2分の1になります。これは、SVNが履歴をローカルに保存していない場合でも、同じファイルを含むSVNリポジトリよりも小さいことを意味します。