Version Control with Git ch8 diffs

Git勉強メモ

出典: 


Diffs

  • diffが提供するもの

    • 2つのファイルがどのように異なるか
    • 一方のファイルを他方に変形するための形式的な方法
  • 拡張

    • 複数ファイルの差分の表現
    • ディレクトリ構造の比較

      • diff -r
  • git diffも、diff -rのようにtree間の比較をできる

Forms of the git diff Command

  • 3つの対象

    • コミットグラフ中の任意のtree
    • 作業ディレクトリ
    • インデックス
  • 4つの基本形

    • git diff

      • 作業ディレクトリとインデックス
      • 出力がある = 作業ディレクトリに未ステージの変更がある
    • git diff commit

      • 作業ディレクトリと指定のコミット
    • git diff —cached commit

      • インデックスと指定のコミット
      • commitの指定がない場合のデフォルトはHEAD

        • これからcommitされる変更
      • --stagedシノニムも可

        • v1.6.1~
    • git diff commit1 commit2

      • 指定の2コミット(が指しているroot tree)のdiff
  • 無数のオプション

    • -M[<n>]

      • リネーム検出の閾値設定
      • -M90%とすると、90%以上同じファイルは削除+追加ではなくリネームとみなす
    • -w, --ignore-all-space

      • 有意でないホワイトスペースの変更を無視
    • --stat

      • 統計情報
    • --color
  • 残念ながらgit diff -aでステージ済・未ステージの変更をまとめて見られたりはしない

    • cf. git commit -aは追跡済のファイルの差分をステージ済・未ステージ問わずまとめてコミットできる
    • まとめて見たいときはgit diff HEADしよう

Simple git diff Example

echo "quux" > file1
git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   file1

no changes added to commit (use "git add" and/or "git commit -a")
  • 変更未ステージ
git diff          # 作業ディレクトリ versus index
git diff HEAD     # 作業ディレクトリ versus HEAD
git diff --cached # インデックス versus HEAD
diff --git a/file1 b/file1
index 257cc56..d90bda0 100644
--- a/file1
+++ b/file1
@@ -1 +1 @@
-foo
+quux
diff --git a/file1 b/file1
index 257cc56..d90bda0 100644
--- a/file1
+++ b/file1
@@ -1 +1 @@
-foo
+quux
  • 【補】まだ変更をgit addしていない = オブジェクトストアにblobが格納されていない
git rev-parse d90bda0
fatal: ambiguous argument 'd90bda0': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
  • 変更をステージ
git add file1
git diff          # 作業ディレクトリ versus index
git diff HEAD     # 作業ディレクトリ versus HEAD
git diff --cached # インデックス versus HEAD
diff --git a/file1 b/file1
index 257cc56..d90bda0 100644
--- a/file1
+++ b/file1
@@ -1 +1 @@
-foo
+quux
diff --git a/file1 b/file1
index 257cc56..d90bda0 100644
--- a/file1
+++ b/file1
@@ -1 +1 @@
-foo
+quux
  • さらに未コミットの差分を追加
echo "baz" > file1
git diff          # 作業ディレクトリ versus index
git diff HEAD     # 作業ディレクトリ versus HEAD
git diff --cached # インデックス versus HEAD
diff --git a/file1 b/file1
index d90bda0..7601807 100644
--- a/file1
+++ b/file1
@@ -1 +1 @@
-quux
+baz
diff --git a/file1 b/file1
index 257cc56..7601807 100644
--- a/file1
+++ b/file1
@@ -1 +1 @@
-foo
+baz
diff --git a/file1 b/file1
index 257cc56..d90bda0 100644
--- a/file1
+++ b/file1
@@ -1 +1 @@
-foo
+quux
  • ステージ済の変更のみコミット
git commit -m "quux uber alles"
  • コミットどうしの比較
git diff HEAD^ HEAD
diff --git a/file1 b/file1
index 257cc56..d90bda0 100644
--- a/file1
+++ b/file1
@@ -1 +1 @@
-foo
+quux

git diff and Commit Ranges

  • 次の2つは等価
git diff A B
git diff A..B
  • cf. git log A..Bとは大違い

    • git log ^A Bの意

      • BおよびBに到達可能なコミットのうち、AおよびAに到達可能でないもの
  • git diff と git logとの違い
git diff git log
歴史 気にしない。2つの状態を比較するだけ とても意識する
対象 2つの状態 コミットの集合
  • git log -p A..B

    • A..Bで指定される各コミットのdiffも同時に見るやつ
  • git diff A..B

    • commit Aとcommit Bの指すtreeの正味のdiffを1つだけ出力

git diff with Path Limiting

git diff HEAD^ HEAD file1
diff --git a/file1 b/file1
index 257cc56..d90bda0 100644
--- a/file1
+++ b/file1
@@ -1 +1 @@
-foo
+quux
  • git logよろしく、-Sオプションが使える

    • 「つるはし」(pickaxe)
    • -S"文字列"で指定した文字列の増減があったファイルのみdiff出力

Comparing How Subversion and Git Derive Diffs

  • 多くのVCS(CVS, SVNなど)では一連のリビジョンを追跡し差分のみ保存する

    • 目的

      • ストレージ空間の節約
      • オーバヘッドを減らす
    • r1095とr1123のdiffを問い合わせたら、その間のdiffをすべてルックアップし、大きなdiffを組み立てる

      • 空間を節約した代わりに時間がかかる
      • リビジョン同士のdiffしか出力できない
  • Gitでは、各コミットでtree(その時点での全ファイル)を保存する

    • 他のtreeに依存しない
    • diffはtreeから導出される
    • 任意の状態同士のdiffを出力できる
    • はやい

英語

  • myriad

    • 無数の