git diff
diff は 2 つの入力データ・セットを取得してそれらの間の変更を出力する機能です。git diff
はさまざまな用途に使える Git コマンドで、実行すると Git データ・ソースに対して diff 機能を実行します。対象のデータ・ソースにはコミット、ブランチ、ファイルなどがあります。このドキュメントでは git diff
の一般的な呼び出しとワークフロー・パターンの違いについて説明します。git diff
コマンドは Git リポジトリの現在の状態を分析するために git status
および git log
と併用されることがよくあります。
diff の見方: 出力
生の出力フォーマット
以下のサンプルはシンプルなリポジトリで実行されるものです。リポジトリは以下のコマンドで作成します。
$:> mkdir diff_test_repo
$:> cd diff_test_repo
$:> touch diff_test.txt
$:> echo "this is a git diff test example" > diff_test.txt
$:> git init .
Initialized empty Git repository in /Users/kev/code/test/.git/
$:> git add diff_test.txt
$:> git commit -am"add diff test file"
[main (root-commit) 6f77fc3] add diff test file
1 file changed, 1 insertion(+)
create mode 100644 diff_test.txt
この時点で git diff
を実行しても何も出力されません。リポジトリには diff になるような変更がないため、これは想定内の挙動です。リポジトリを作成したら、diff_test.txt
ファイルを追加してそのコンテンツを変更し、diff の出力を実際に見てみます。
関連資料
Git Branch コマンド
ソリューションを見る
Bitbucket Cloud での Git の使用方法についてのチュートリアルです。
$:> echo "this is a diff example" > diff_test.txt
このコマンドを実行すると、diff_test.txt
ファイルのコンテンツに変更が加えられます。変更が完了したら、diff を表示して出力を分析します。ここで git diff
を実行すると以下の出力が生成されます。
diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example
では diff の出力をさらに詳しく見ていきましょう。
1. 比較の入力
diff --git a/diff_test.txt b/diff_test.txt
この行には diff の入力ソースが表示されています。a/diff_test.txt
と b/diff_test.txt
が diff に渡されているのがわかります。
2. メタデータ
index 6b0c6cf..b37e70a 100644
この行には内部 Git メタデータの一部が表示されています。この情報が必要になることはほぼないでしょう。この出力の数字は Git オブジェクトバージョンのハッシュ識別子に対応しています。
3. 変更箇所のマーカー
--- a/diff_test.txt
+++ b/diff_test.txt
これらの行は各 diff 入力ソースに記号を割り当てる凡例です。今回のケースでは、a/diff_test.txt
の変更が ---
で示され、b/diff_test.txt
の変更が +++
記号で示されています。
4. diff チャンク
diff 出力のその他の部分は diff の「チャンク」の一覧です。diff ではファイルで変更されたセクションだけが表示されます。現在のサンプルでは単純なシナリオで作業しているため、チャンクは 1 つしかありません。チャンクには独自のきめ細かな出力セマンティックがあります。
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example
最初の行はチャンク ヘッダーです。各チャンクの先頭には、@@
記号で囲まれたヘッダーがあります。ヘッダーの中身はファイルに加えられた変更の概要になっています。今回のシンプルなサンプルには「-1 +1」がありますが、これは 1 行目に変更があることを意味しています。より現実に近い diff では、以下のようなヘッダーが表示されます。
@@ -34,6 +34,8 @@
このヘッダーのサンプルでは、34 行目から 6 行分が抽出されています。さらに、34 行目から 8 行分が追加されています。
diff チャンクの残りの部分には最新の変更が表示されます。変更された各行の先頭には、変更がどのバージョンの diff 入力のものかを示す +
または -
記号が先頭に付きます。前に説明したように、-
は a/diff_test.txt
の変更、+ は b/diff_test.txt
の変更を示しています。
変更の強調表示
1. git diff --color-words
git diff
にはよりきめ細かいレベルで変更を強調表示できる特別なモード --color-words
があります。このモードでは追加された行と削除された行を空白でトークン化してそれらの差分を出します。
$:> git diff --color-words
diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
this is agit difftest example
これで、変更された単語に色付けされたものだけが出力に表示されるようになりました。
2. git diff-highlight
Git ソースをクローンすると、contrib というサブディレクトリに気づくでしょう。このディレクトリには Git 関連のツールや、git の基本機能としてまだ採用されていないこまごまとした面白いものが大量に入っています。たとえば、diff-highlight という Perl スクリプトがあります。diff-highlight は diff 出力で一致する行をグループ化して、変更された、通常の単語よりも小さい塊を強調表示します。
$:> git diff | /your/local/path/to/git-core/contrib/diff-highlight/diff-highlight
diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example
これで、最小限の変更だけが diff として表示されるようになりました。
バイナリファイルの差分を取る
これまで実際に説明してきたテキスト ファイル ユーティリティだけでなく、git diff
をバイナリ ファイルに対しても実行できます。ただし、デフォルトの出力はあまり役に立ちません。
$:> git diff
Binary files a/script.pdf and b/script.pdf differ
Git には、diff を実行する前にシェル コマンドを指定してバイナリ ファイルの中身をテキストに変換できる機能があります。ただし、これを行うにはちょっとした設定が必要です。まず、特定の種類のバイナリ ファイルをテキストに変換する方法を記入した textconv フィルターを指定する必要があります。今回は pdftohtml (homebrew から利用可能) というシンプルなユーティリティを使って PDF を人間が読める形の HTML に変換します。1 つのリポジトリでこれを設定するには、.git/config
ファイルを編集するか、全体に実行する場合は ~ /.gitconfig
を編集します。
[diff "pdfconv"]
textconv=pdftohtml -stdout
この後は 1 つ以上のファイル パターンを pdfconv フィルターと関連付けるだけです。これを行うには .gitattributes
ファイルをリポジトリのルートに作成します。
*.pdf diff=pdfconv
設定が完了したら、git diff
はまず設定済みのコンバーター スクリプトでバイナリ ファイルを実行してコンバーター出力の差分を出します。zip や jar、その他のアーカイブ形式を含むすべての種類のバイナリ ファイルで同じ手法を使って有用な差分を出せます。pdf2html の代わりに unzip -l
(または類似のコマンド) を使ってコミット イメージ間で追加または削除されたパスを表示します。exiv2 を使ってイメージ ディメンション ドキュメントなどのメタデータの変更を表示できます。.odf や .doc などその他のドキュメント形式をプレーン テキストに変換する変換ツールもあります。いざという時には、正式なコンバーターがなくてもほとんどの場合、ストリングを使ってバイナリ ファイルを変換できます。
ファイルの比較: git diff ファイル
git diff
コマンドには明示的なファイル パス オプションを渡せます。ファイル パスを git diff
に渡すと、指定したファイルだけに diff 操作を実行できます。以下のサンプルでこの方法を説明します。
git diff HEAD ./path/to/file
このサンプルでは呼び出し時に対象を /path/to/file
に限定していて、作業ディレクトリとインデックスの特定の変更を比較することでまだステージされていない変更を表示しています。デフォルトでは、git diff
は HEAD
との比較を実行します。上のサンプルの、git diff ./path/to/file
から HEAD
を省略しても同じ結果が得られます。
git diff --cached ./path/to/file
--cached
オプションを指定して git diff
を呼び出すと、ステージ済みの変更とローカル リポジトリを比較して差分を出します。--cached
オプションは --staged
と同義です。
すべての変更を比較する
ファイル パスを指定せずに git diff
を呼び出すと、リポジトリ全体の変更を比較します。上のファイル固有のサンプルは ./path/to/file
引数なしで呼び出せて、ローカル リポジトリのすべてのファイルで同じ出力結果が出ます。
最後のコミット以降の変更
デフォルトでは、git diff
は最後のコミット以降コミットされていない変更を表示します。
git diff
2 つの異なるコミットを比較する
git diff
に Git ref を渡して diff にコミットできます。ref の例としては、HEAD
、タグ、ブランチ名があります。Git のすべてのコミットにはコミット ID があり、GIT LOG
を実行して取得できます。また、このコミット IDを git diff
に渡せます。
git log --pretty=oneline
957fbc92b123030c389bf8b4b874522bdf2db72c add feature
ce489262a1ee34340440e55a0b99ea6918e19e7a rename some classes
6b539f280d8b0ec4874671bae9c6bed80b788006 refactor some code for feature
646e7863348a427e1ed9163a9a96fa759112f102 add some copy to body
$:> git diff 957fbc92b123030c389bf8b4b874522bdf2db72c ce489262a1ee34340440e55a0b99ea6918e19e7a
ブランチを比較する
2 つのブランチを比較する
ブランチは git diff
への他のすべての ref 入力のように比較されます。
git diff branch1..other-feature-branch
このサンプルではドット演算子を紹介します。このサンプルの 2 つのドットは、diff 入力が両方のブランチの先端であることを示しています。ドットを省略した場合も同じ結果が得られ、ブランチ間にスペースが使用されます。またドットが 3 つある演算子もあります。
git diff branch1...other-feature-branch
ドットが 3 つある演算子は、最初の入力パラメーター branch1
を変更して diff を開始します。これによって、2 つの diff 入力、branch1
の共有されている祖先、other-feature-branch の間の、共有されている共通の祖先のコミットの ref に branch1
を変更します。最後の入力パラメーターは other-feature-branch の先端のまま変わりません。
2 つのブランチからファイルを比較する
ブランチをまたいで特定のファイルを比較するには、ファイルのパスを 3 番目の引数として git diff
に渡します。
git diff main new_branch ./diff_test.txt
要約
このページでは、Git 差分プロセスと git diff
コマンドを取り上げました。git diff
出力の見方と、出力に含まれるさまざまなデータについて取り上げました。強調表示と色で git diff
出力を変更する様子を説明するサンプルを示しました。ブランチや特定のコミットのファイルで差分を取る方法など、さまざまな diff の手法を紹介しました。git diff
コマンド以外にも、git log
と git checkout
を使いました。
この記事を共有する
次のトピック
おすすめコンテンツ
次のリソースをブックマークして、DevOps チームのタイプに関する詳細や、アトラシアンの DevOps についての継続的な更新をご覧ください。