この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:5
ページ更新者:T
更新日時:2026-06-11 07:07:02

タイトル: 参照(ORIG_HEAD, HEAD, FETCH_HEAD)
SEOタイトル: Git の特殊参照 HEAD / ORIG_HEAD / FETCH_HEAD / MERGE_HEAD の意味と使い分け

この記事の要点
  • HEAD = 現在チェックアウトしているコミット(ブランチや detached commit を指すシンボリック参照)
  • ORIG_HEAD = merge / rebase / reset / pull 等の危険操作直前の HEAD を自動退避
  • FETCH_HEAD = 最後の git fetch で取得したコミット(リモート最新)
  • MERGE_HEAD / CHERRY_PICK_HEAD / REVERT_HEAD = それぞれの操作中だけ存在する一時参照
  • やらかしたら git reflog で履歴を確認 → git reset --hard ORIG_HEAD1 つ前の状態に戻せる
  • 参照ファイルは .git/HEAD / .git/ORIG_HEAD 等にプレーンテキストで存在

Git の特殊参照とは

Git では「コミットを指す名前」のことを参照(ref)と呼びます。ブランチ名(main など)やタグ名のほかに、Git が内部的に自動管理する特殊参照がいくつかあり、これらを理解するとreset / merge / rebase失敗からの復旧が格段に楽になります。

参照意味更新タイミング
HEAD現在のコミットcommit / checkout / reset 毎
ORIG_HEAD危険操作前の HEAD バックアップmerge / rebase / reset / pull / am
FETCH_HEAD最後に fetch したコミット群fetch / pull
MERGE_HEADマージしようとしている相手merge 開始時(コンフリクト中のみ)
CHERRY_PICK_HEADcherry-pick 中の対象コミットcherry-pick 中のみ
REVERT_HEADrevert 中の対象コミットrevert 中のみ

HEAD: 現在のコミット

HEAD は「いまどのコミットを見ているか」を表します。通常はブランチ名を指しますが、git checkout 等でdetached HEAD 状態にすると、コミットを直接指すこともあります。

# HEAD の中身を確認
cat .git/HEAD
# → ref: refs/heads/main   (通常はブランチを指す)

cat .git/refs/heads/main
# → e3f4a2b...   (コミットハッシュ)

# HEAD が指すコミットを表示
git rev-parse HEAD
git show HEAD
git log -1 HEAD

# 直前のコミット
git show HEAD~1
git show HEAD^

# 2 つ前
git show HEAD~2
git show HEAD^^

# HEAD の親が複数ある(マージコミット)場合
git show HEAD^1    # 第 1 親
git show HEAD^2    # 第 2 親

ORIG_HEAD: 危険操作前のバックアップ

Git は merge / rebase / reset / pull / am など履歴を書き換える可能性のある操作の直前に、その時点の HEAD を ORIG_HEAD として保存します。「やらかしたらまず ORIG_HEAD」と覚えておくと救われます。

# やらかしパターン1: reset --hard で消した
git log --oneline
# a1b2c3d (HEAD) ← いまここ
# e4f5g6h ← 大事なコミット
git reset --hard HEAD~3   # 3 つ消してしまった!

# → ORIG_HEAD には reset 直前の a1b2c3d が残っている
git show ORIG_HEAD

# 元に戻す
git reset --hard ORIG_HEAD

# やらかしパターン2: マージで予想外の変更が入った
git merge feature-x
# 大量にコンフリクト&意図しない変更
git merge --abort                # 進行中ならこれ
# 完了済なら
git reset --hard ORIG_HEAD       # マージ前に戻る

# やらかしパターン3: rebase が大荒れ
git rebase main
# 履歴がぐちゃぐちゃに
git rebase --abort               # 進行中なら
git reset --hard ORIG_HEAD       # 完了済なら

FETCH_HEAD: 最後の fetch 結果

git fetch でリモートから取得したコミット群が FETCH_HEAD に記録されます。git pull は内部的に「fetchFETCH_HEAD を merge」を行っています。

# fetch だけ実行(merge はしない)
git fetch origin

cat .git/FETCH_HEAD
# 8c1d... not-for-merge   branch 'develop' of github.com:...
# a2f9... branch 'main'    of github.com:...
# → "not-for-merge" は明示的に取得していないブランチ

# 取得した最新を差分確認
git log HEAD..FETCH_HEAD --oneline
git diff HEAD FETCH_HEAD

# 手動でマージ
git merge FETCH_HEAD

# 特定リモートだけ FETCH_HEAD を見たい
git fetch origin main
git show FETCH_HEAD

MERGE_HEAD: マージ中の相手

マージがコンフリクトで止まっている間のみ存在します。コンフリクト解消の指針になります。

git merge feature-x
# CONFLICT! ... が表示
# → .git/MERGE_HEAD に feature-x の先頭コミットが書かれる

cat .git/MERGE_HEAD
# 9f8e7d6c5b4a...

# コンフリクト中に「相手側の変更」を確認
git show MERGE_HEAD:src/Login.php

# 「自分側」と「相手側」を見比べる
git show HEAD:src/Login.php          # 自分(現在ブランチ)
git show MERGE_HEAD:src/Login.php    # 相手

# マージを中断(HEAD と MERGE_HEAD 関連を全部リセット)
git merge --abort

reflog: 全ての HEAD 移動の履歴

ORIG_HEAD だけでは「2 操作前」までしか戻せませんが、git reflog なら過去 90 日分の HEAD 移動を全て確認できます。

# 過去の HEAD 移動を一覧
git reflog
# a1b2c3d HEAD@{0}: reset: moving to HEAD~3
# e4f5g6h HEAD@{1}: commit: 大事な変更
# 1234567 HEAD@{2}: commit: その前

# 特定の地点に戻る
git reset --hard HEAD@{1}
git reset --hard e4f5g6h    # ハッシュ指定でも可

# 指定ブランチの reflog
git reflog show main

# 全 ref の reflog
git reflog show --all

# 期限切れ前に手動 gc 防止(90 日デフォルト)
git config gc.reflogExpire 200.days

参照を指定する記法(rev 表記)

記法意味
HEAD現在
HEAD^ / HEAD~11 つ前
HEAD~33 つ前
HEAD^2マージコミットの第 2 親
HEAD@{2}reflog の 2 つ前
HEAD@{yesterday}昨日時点の HEAD
HEAD@{2.hours.ago}2 時間前の HEAD
main..HEADmain から HEAD までの差分
main...HEAD共通祖先からの両方向差分

FAQ

Q: ORIG_HEAD はいつ消える?
A: 次の危険操作(merge / reset / rebase 等)が走るまで保持されます。pull を立て続けにやると上書きされるので注意。確実に保存したい場合は別ブランチ git branch backup ORIG_HEAD を作ってから操作。

Q: detached HEAD 状態でコミットしたら?
A: ブランチに紐付かないコミットになり、checkout で離れると参照されなくなります。git reflog で見つけて git branch save で救出。

Q: reflog にも無いコミットを復元したい
A: git fsck --lost-found.git/lost-found/ に dangling commit が出ます。gc されていなければ救えます。