Git rev-spec チートシート:^/~/A..B/A...B を完全図解
Git のコミット履歴を自由自在に操作したいと思ったことはありませんか。複雑なブランチ構造の中で、特定のコミットやコミット範囲を正確に指定できれば、マージやリベース、ログの確認がぐっと効率的になります。
しかし、^や~、..や...といった記号を見ても、「どれがどういう意味だっけ?」と混乱してしまう方も多いのではないでしょうか。本記事では、Git の rev-spec(リビジョン指定)記法を徹底的に図解し、実務ですぐに使えるチートシートとしてまとめました。
rev-spec 早見表
各記法の特徴を一覧で確認できます。
| # | 記法 | 意味 | 用途例 | 結果 |
|---|---|---|---|---|
| 1 | HEAD^ | HEAD の第 1 親コミット | git show HEAD^ | 1 つ前のコミットを表示 |
| 2 | HEAD^2 | HEAD の第 2 親コミット(マージ時) | git show HEAD^2 | マージ元ブランチの最新コミット |
| 3 | HEAD~ | HEAD の第 1 親コミット | git show HEAD~ | 1 つ前のコミットを表示 |
| 4 | HEAD~3 | HEAD から 3 世代前のコミット | git log HEAD~3..HEAD | 直近 3 コミットのログ |
| 5 | A..B | A より後で B に到達可能なコミット群(A を除く) | git log main..feature | feature ブランチ独自のコミット |
| 6 | A...B | A と B の共通祖先以降の対称差分 | git log --left-right main...feature | 両ブランチの差分コミット |
背景
Git のコミット履歴はグラフ構造
Git はコミット履歴を 有向非巡回グラフ(DAG) として管理しています。各コミットは親コミットへの参照を持ち、ブランチやマージによって複雑なツリー構造を形成します。
このグラフ構造を効率的に操作するために、Git では rev-spec(リビジョン指定) という記法が用意されています。
図の意図:コミット履歴がどのようなグラフ構造になっているかを示します。
mermaidgitGraph
commit id: "A"
commit id: "B"
branch feature
commit id: "D"
commit id: "E"
checkout main
commit id: "C"
merge feature id: "F"
commit id: "G"
この図では、main ブランチと feature ブランチが分岐し、最終的にマージされている様子がわかります。コミット F はマージコミットであり、複数の親を持つ特殊なコミットです。
rev-spec が必要な場面
実務では以下のような場面で rev-spec を活用します。
- 特定のコミット範囲のログ確認:「このブランチにしかないコミット」を調べる
- リベースやチェリーピック:特定の親コミットを基準に操作する
- マージコミットの調査:どのブランチからマージされたかを確認する
- 差分の抽出:2 つのブランチ間の変更内容を比較する
これらを正確に行うには、^、~、..、... の使い分けが不可欠です。
課題
記法の違いがわかりにくい
Git を使い始めたばかりの開発者にとって、以下のような疑問が生じます。
HEAD^とHEAD~は何が違うのか?A..BとA...Bのドット 2 つと 3 つの違いは?- マージコミットの場合、どの親を指定すればいいのか?
公式ドキュメントを読んでも、抽象的な説明が多く、実際のコミット構造と結びつけて理解するのが難しいという課題があります。
誤った指定によるトラブル
rev-spec の理解が不十分なまま操作すると、以下のようなトラブルが発生します。
| # | 誤った操作例 | 発生する問題 |
|---|---|---|
| 1 | git rebase HEAD^ を意図せず実行 | 想定外のコミットを基準にリベースされる |
| 2 | A..B と A...B を混同 | 抽出したいコミット範囲が異なる |
| 3 | マージコミットで ^2 を指定し忘れ | マージ元ブランチの履歴を参照できない |
こうしたミスを防ぐには、各記法の 動作原理を図で理解 することが重要です。
解決策
^ と ~ の使い分け
^(キャレット)と~(チルダ)は、いずれも親コミットを指定する記法ですが、意味と用途が異なります。
^(キャレット):親の「選択」
^ は どの親コミットを選ぶか を指定します。
typescript// 基本構文
HEAD ^ // 第1親コミット(HEAD^ と HEAD^1 は同じ)
HEAD ^
2; // 第2親コミット(マージコミットの場合)
HEAD ^ 3; // 第3親コミット(3方向マージの場合)
マージコミットは複数の親を持つため、^ で何番目の親かを明示的に指定できます。
図の意図:マージコミットにおける ^ の動作を示します。
mermaidflowchart RL
G["G<br/>(HEAD)"] -->|"^1"| F["F<br/>(マージコミット)"]
F -->|"^1"| C["C<br/>(main側の親)"]
F -->|"^2"| E["E<br/>(feature側の親)"]
C --> B["B"]
E --> D["D"]
D --> B
B --> A["A"]
この図から、F^1 は main 側の親である C を、F^2 は feature 側の親である E を指すことがわかります。
~(チルダ):親の「遡り」
~ は 第 1 親を何世代遡るか を指定します。
typescript// 基本構文
HEAD~ // 第1親コミット(HEAD~ と HEAD~1 は同じ)
HEAD~2 // 第1親の第1親(2世代前)
HEAD~3 // 第1親の第1親の第1親(3世代前)
~ は常に 第 1 親のみを辿る ため、マージコミットでも第 2 親以降は参照できません。
図の意図:~ による世代遡りの動作を示します。
mermaidflowchart RL
G["G<br/>(HEAD)"] -->|"~1"| F["F"]
F -->|"~2"| C["C"]
C -->|"~3"| B["B"]
B -->|"~4"| A["A"]
F -.->|"無視される"| E["E"]
E -.-> D["D"]
D -.-> B
この図では、HEAD~3 は常に第 1 親を辿って B に到達し、E や D は無視されます。
組み合わせ例
^ と ~ は組み合わせて使えます。
bash# 第2親の2世代前
git show HEAD^2~2
# 第1親の第2親(複雑なマージ構造の場合)
git show HEAD~^2
A..B と A...B の使い分け
ドット記法はコミット範囲を指定する際に使います。
A..B(ドット 2 つ):範囲指定
A..B は 「A より後で B に到達可能なコミット」 を指します(A 自体は含まれません)。
bash# feature ブランチにしかないコミットを表示
git log main..feature
図の意図:A..B で抽出されるコミット範囲を示します。
mermaidflowchart RL
G["G<br/>(feature)"] -.->|"含まれる"| F["F"]
F -.->|"含まれる"| E["E"]
E -.->|"含まれる"| D["D"]
D --> C["C<br/>(main)"]
C --> B["B"]
B --> A["A"]
style D fill:#90EE90
style E fill:#90EE90
style F fill:#90EE90
style G fill:#90EE90
main..feature は、main には含まれず feature にのみ到達可能なコミット(D、E、F、G)を抽出します。
A...B(ドット 3 つ):対称差分
A...B は 「A と B の共通祖先以降の、どちらか一方にのみ含まれるコミット」 を指します。
bash# main と feature の両方の差分を表示
git log --left-right main...feature
図の意図:A...B で抽出されるコミットの対称性を示します。
mermaidflowchart RL
G["G<br/>(feature)"] -.->|"右側"| F["F"]
F -.->|"右側"| E["E"]
E -.->|"右側"| D["D"]
H["H<br/>(main)"] -.->|"左側"| C["C"]
C --> B["B<br/>(共通祖先)"]
D --> B
B --> A["A"]
style C fill:#FFB6C1
style D fill:#90EE90
style E fill:#90EE90
style F fill:#90EE90
style G fill:#90EE90
style H fill:#FFB6C1
main...feature は、共通祖先 B 以降の main 側(C、H)と feature 側(D、E、F、G)の両方を抽出します。--left-right オプションを付けると、どちら側のコミットか明示されます。
実務での活用パターン
以下の表は、よく使う rev-spec パターンをまとめたものです。
| # | コマンド例 | 用途 |
|---|---|---|
| 1 | git log HEAD~5..HEAD | 直近 5 コミットのログ表示 |
| 2 | git diff HEAD^..HEAD | 最新コミットの差分確認 |
| 3 | git log main..feature | feature ブランチ独自のコミット |
| 4 | git log --left-right main...feature | 両ブランチの差分を左右で表示 |
| 5 | git show HEAD^2 | マージコミットの第 2 親を表示 |
| 6 | git rebase -i HEAD~3 | 直近 3 コミットをインタラクティブリベース |
具体例
例 1:マージコミットの親を調べる
マージ後、どのブランチからマージされたかを確認したい場合があります。
bash# 最新コミットがマージコミットか確認
git log -1 --pretty=%P HEAD
このコマンドは、HEAD の親コミットのハッシュを表示します。親が 2 つあればマージコミットです。
bash# 第1親(main側)のログを表示
git log HEAD^1
# 第2親(feature側)のログを表示
git log HEAD^2
図の意図:マージコミットの親を特定するフローを示します。
mermaidflowchart TD
start["マージコミットの確認"] --> check["git log -1 --pretty=%P HEAD"]
check --> judge{親が2つ以上?}
judge -->|Yes| merge["マージコミットである"]
judge -->|No| normal["通常のコミット"]
merge --> show1["git log HEAD^1<br/>(第1親の履歴)"]
merge --> show2["git log HEAD^2<br/>(第2親の履歴)"]
例 2:ブランチ間の差分を抽出
feature ブランチを main にマージする前に、変更内容を確認します。
bash# feature にしかないコミットを表示
git log main..feature
出力例:
plaintextcommit f8a3b2c
Author: Yuki <yuki@example.com>
Date: Mon Jan 15 10:30:00 2025 +0900
Add new feature
commit d4e6f1a
Author: Yuki <yuki@example.com>
Date: Mon Jan 15 09:00:00 2025 +0900
Fix typo
main には含まれず、feature にのみ存在するコミットが表示されます。
例 3:対称差分でレビュー
両方のブランチの差分を同時に確認し、レビューを効率化します。
bash# 両ブランチの差分を左右表示
git log --left-right --oneline main...feature
出力例:
plaintext< a1b2c3d Update README
< e4f5g6h Fix bug in parser
> d4e6f1a Fix typo
> f8a3b2c Add new feature
< は main 側、> は feature 側のコミットを示します。
例 4:特定世代のコミットを参照
リリース前に、3 コミット前の状態を確認したい場合があります。
bash# 3コミット前の状態をチェックアウト
git checkout HEAD~3
この操作で、現在から 3 世代前のコミット状態に移動できます。元に戻すには以下を実行します。
bash# 元のブランチに戻る
git checkout main
例 5:複雑な親の組み合わせ
複数のマージが重なった履歴で、特定のコミットを参照します。
bash# 第2親の2世代前を表示
git show HEAD^2~2
図の意図:複雑な親の組み合わせを視覚化します。
mermaidflowchart RL
HEAD["HEAD"] -->|"^1"| M1["M1<br/>(第1親)"]
HEAD -->|"^2"| M2["M2<br/>(第2親)"]
M2 -->|"~1"| F1["F1"]
F1 -->|"~2"| F2["F2"]
F2 --> F3["F3"]
style F2 fill:#FFD700
HEAD^2~2 は、HEAD の第 2 親である M2 から第 1 親を 2 世代遡った F2 を指します。
まとめ
Git の rev-spec 記法は、コミット履歴を正確に操作するための強力なツールです。本記事では、以下の要点を図解とともに解説しました。
まず、^ と ~ の違いについては、^ が親の「選択」、~ が親の「遡り」であることを押さえておきましょう。マージコミットでは ^2 で第 2 親を、~3 で 3 世代前を参照できます。
次に、.. と ... の違いでは、A..B が「A より後で B に到達可能なコミット」、A...B が「共通祖先以降の対称差分」であることを理解することが重要です。ブランチ間の差分確認やレビューで活用できます。
これらの記法を使いこなせば、リベース、チェリーピック、マージの操作がより正確かつ効率的になります。ぜひ実務で試してみてください。
図で理解できる要点:
- マージコミットは複数の親を持ち、
^で親を選択、~で世代を遡る A..Bは範囲指定、A...Bは対称差分を抽出する- 組み合わせることで複雑な履歴構造も正確に参照できる
関連リンク
articleGit rev-spec チートシート:^/~/A..B/A...B を完全図解
articleGit worktree 速習:複数ブランチを同時並行で開発する最短レシピ
articleGit の依存取り込み比較:subtree vs submodule — 運用コストと安全性の実態
articleGit の index.lock 残留問題を解決:並行実行・クラッシュ後の正しい対処法
articleGit ワークフロー地図 2025:トランクベース/フォーク/リリースブランチの選び方
articleGit ガバナンス運用:レビュー必須・チェックルール・承認フローの作り方
articleMistral 使い方入門:要約・説明・翻訳・書き換えの基礎プロンプト 20 連発
articleGitHub Actions のジョブ分割設計:needs と outputs でデータを安全に受け渡す
articleGit rev-spec チートシート:^/~/A..B/A...B を完全図解
article【早見表】JavaScript MutationObserver & ResizeObserver 徹底活用:DOM 変化を正しく監視する
articlehtmx × Laravel/PHP 導入手順:Blade パーシャルとルート設計の落とし穴回避
articleHomebrew の Bottle vs ソースビルド比較検証:時間・サイズ・再現性の差をデータで解説
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来