web-dev-qa-db-ja.com

GITはファイルデルタを保存しないという事実にもかかわらず、以前のファイルバージョンにロールバックできますか(無制限の時間?)

私が読んだ Gitはファイルデルタを保存しません。これが当てはまる場合、以前のバージョンへのファイルのロールバックをどのようにサポートしますか?ファイル全体を保存している場合、ディスク上のリポジトリスペースは管理できないほど大きくなる必要があります。 Gitはファイルのロールバックとファイルバージョン1への差分をサポートしていますか?ファイルに関連するバージョン管理の概念もサポートしていますか?これは、VCS/DVCSと私のニーズを理解するために不可欠です(私は信じています)。チェックインしようとしているものを以前のバージョンと比較できるようにする必要があります。

14
Pete Alvin

Gitはそれ自体で情報を破棄しません*。すべてのファイルの以前のバージョンはすべて、元に戻す、差分、検査などにいつでも利用できます。

ツリー全体と個別ファイル

調整しようとしているのは、Gitの履歴モデルがツリー全体に焦点を合わせているという事実とは対照的に、個々のファイルの古いバージョンにアクセスするという考えです。ツリー全体のバージョン管理では、(たとえば)foo.cのバージョンが10個のfoo.c-変更前と10個のツリー全体の変更前に存在していたため、確認するにはもう少し作業が必要です。

# 10 foo.c-changes ago
git show $(git rev-list -n 10 --reverse HEAD -- foo.c | head -1):foo.c

# 10 whole-tree-changes ago
git show HEAD~10:foo.c

ツリー指向の利点、主にツリー全体のさまざまな部分に加えられた相互依存の変更の単位としてコミットを表示する機能は、一般に、余分な入力(エイリアス、スクリプトなどで軽減できます)とCPU時間を大幅に上回ります。過去のコミットを掘り下げるのに費やしました。

ストレージ効率

新しいオブジェクト(たとえば、以前に表示されていない内容のファイル)がシステムに入ると、プレーン(zlib)圧縮で「ルーズオブジェクト」として保存されます。十分な数の緩いオブジェクトが蓄積されると(gc.auto構成オプションに基づく;またはユーザーがgit gcまたは下位レベルのパッキングコマンドの1つを実行するとき)、Gitは収集します多くの緩いオブジェクトを1つの「パックファイル」にまとめます。

パックファイル内のオブジェクトは、プレーンな圧縮データ(ルーズオブジェクトと同じ、他のオブジェクトとバンドルされているだけ)として、または他のオブジェクトに対する圧縮デルタとして保存できます。デルタは、構成可能な深さ(pack.depth)にチェーン化でき、任意の適切なオブジェクトに対して作成できます(pack.windowは、Gitが最適なデルタベースを検索する範囲を制御します。歴史的に無関係なファイルのバージョンは、そうすることで良好なデルタ圧縮が得られる場合は、ベースとして使用されます)。深度とウィンドウサイズの構成がデルタ圧縮エンジンに与える許容範囲は、多くの場合、CVSスタイルの単純な1バージョン対次のバージョン/前のバージョンの「差分」圧縮よりも優れたデルタ圧縮になります。

この積極的なデルタ圧縮(通常のzlib圧縮と組み合わせたもの)により、Gitリポジトリ(完全な履歴と非圧縮の作業ツリー)が単一のSVNチェックアウト(非圧縮の作業ツリーと元のコピー)よりも少ないスペースで済むことがよくあります。

Gitがオブジェクトを格納する方法 および パックファイルGitコミュニティブック のセクションを参照してください。また、 git pack-objectsmanpage

*「履歴の書き換え」やgit resetなどのコマンドを使用して、Gitがコミットを破棄するように指示できますが、これらの場合でも、Gitは新しく破棄されたコミットにしばらく「ハングアップ」します。あなたがそれらを必要とすると決めた場合に備えて。 git reflog および git Prune を参照してください。

45
Chris Johnsen

gitは実際にはファイルのデルタを保存しますが、ファイルツリー全体のデルタとして保存します。

バージョン間の違いを確認するには、次のいずれかを実行します。

  1. git diff-最後にチェックインしたバージョンと、変更されたがgit addが実行されていないファイルとの違いを示します。
  2. git diff --cached-以前のバージョンと、git addが実行されたが、コミットされていないすべてのファイルとの違いを示します
  3. git diff commitid-commitidで指定された現在の作業ディレクトリと以前のコミットの違いを表示します
  4. git diff commita..commitb-2つのコミットaとbの違いを示します。コミットは、ブランチやタグなどのシンボリック名にすることもできます。
1
edgester

同じページで読むことができます:

.。

その結果、Gitはソースコードツリーの下のどのレベルでもファイルリビジョンの関係を明示的に記録しません。

.。

プロジェクト全体よりも、単一のファイルの変更履歴を調べる方が少し費用がかかります。特定のファイルに影響を与える変更の履歴を取得するには、Gitはグローバル履歴を調べてから、各変更がそのファイルを変更したかどうかを判断する必要があります。ただし、履歴を調べるこの方法では、Gitは、任意のファイルセットへの変更を示す単一の履歴を同等の効率で生成できます。たとえば、ソースツリーのサブディレクトリと関連するグローバルヘッダーファイルは非常に一般的なケースです。

.。

したがって、ファイルの以前のリビジョンに戻って、2つのファイルを比較できます。

1
Tamara Wijsman