git log と git diff の .. と ...:同じ記号で意味が変わる理由
git log で A..B と A...B が選ぶコミット、git diff で2つの記号が比べる地点を、Git 公式ドキュメントと実行例で整理します。プルリクエストの差分がどちらかも扱います。
git log main..feature と git log main...feature は点が1つ違うだけですが、選ばれるコミットが異なることがあります。同じ記法を git diff に使うと、意味がまた変わります。log は点の記法をコミットの集合として読み、diff は比べる2つの端点として読むからです。
そのため、以下の例のようにブランチが分かれた履歴では、log の点3つは両方のブランチのコミットを選び、git diff main...feature は main だけで起きた変更を含めません。これはこの履歴でそうなったというだけで、点3つがいつも多く、あるいはいつも少なく表示するという決まりはありません。出力の量はコミットグラフとファイルの内容で変わります。例は macOS 15.6.1 の git 2.55.0 で実行しました。
例のリポジトリ
base コミットから feature ブランチを作り、両側にコミットを1つずつ追加しました。
feature:feature.txtを追加main:main.txtを追加
この単純な履歴では、2つのブランチの先端の最良の共通祖先(best common ancestor)は base です。Git はこれを merge base と呼び、git merge-base main feature で確認できます。
図:この例の履歴での結果です。履歴の形が違えば、2つの記法の出力の差も変わります。
git log では:コミットの集合
gitrevisions によると、r1..r2 は ^r1 r2 の省略形です。r2 からたどれるコミットのうち、r1 からたどれるものを除いたものです。
$ git log --format=%s main..feature
feature: add feature.txt
r1...r2 は対称差です。どちらか一方からだけたどれるコミットを選び、両方からたどれるものは除きます。--left-right を付けると、左側(r1)から来たコミットには <、右側(r2)から来たコミットには > が付きます。
$ git log --left-right --format='%m %s' main...feature
< main: add main.txt
> feature: add feature.txt
どちらの記法でも片方を省略でき、省略した側は HEAD になります。origin.. は origin..HEAD と同じです。
git diff では:2つの地点の比較
git-diff のドキュメントは、diff は2つの端点を比べるコマンドであり、ここでの .. と ... は gitrevisions でいう範囲ではない、と明記しています。
git diff A..B は git diff A B と同じです。2つのコミットのスナップショットをそのまま比べます。
$ git diff --stat main..feature
feature.txt | 1 +
main.txt | 1 -
2 files changed, 1 insertion(+), 1 deletion(-)
feature で main.txt を削除したことはないのに、削除として表示されます。ブランチが分かれたあとで main に追加されたファイルなので feature にはなく、2つのスナップショットを並べると消えたように見えるからです。
git diff A...B は git diff $(git merge-base A B) B と同じです。ブランチが分かれた地点から B までの、B 側の変更を表示します。
$ git diff --stat main...feature
feature.txt | 1 +
1 file changed, 1 insertion(+)
GitHub のドキュメントは、プルリクエストの差分はこの3点方式だと説明しています(2026年10月3日確認)。「このブランチは何を変えたのか」を知りたいなら、たいていは3点のほうです。
まとめ
| 記法 | git log | git diff |
|---|---|---|
A..B |
B からたどれて A からはたどれないコミット | A と B のスナップショットを直接比較 |
A...B |
A と B のどちらか一方からだけたどれるコミット | merge base から B までの変更 |
履歴の形によっては、2つの記法の結果が同じになります。main が feature の祖先であれば、たとえば feature を main から作成したあと main が進んでいなければ、log では main..feature と main...feature は同じコミットを選び、diff でも両方とも同じ2つのスナップショットを比べます。
merge base が複数あるとき
ブランチ同士を互いにマージした履歴(criss-cross merge)では、2つのコミットの最良の共通祖先が複数になることがあります。git diff A...B が使うのは、--all なしの git merge-base A B が返す merge base 1つだけです。git-merge-base のドキュメントによると、候補が複数あるときにどれが返るかは決まっていません。
git merge-base --all A B で候補が複数あるかどうかは確かめられますが、それで3点の diff が使う merge base が変わるわけではありません。
diff 出力の @@ 行の読み方は unified diff の読み方 にまとめています。
参照した仕様とドキュメント
リンクと内容は2026年10月3日に確認しました。GitHub の画面の動作は変わることがあります。