【Git】addの取り消し方法|restore –staged・reset HEAD・ハンク単位unstage完全ガイド

【Git】add の取り消し方法 Git

git add .で不要なファイルまでステージしてしまった」「1つのファイルの中で、コミットしたい変更とそうでない変更を混ぜてadd してしまった」——git addの取り消しは日常的に必要になる操作です。幸いこれは破壊的な操作ではなく、ステージング(index)から作業ツリーに変更を戻すだけなので、失敗してもファイルの変更自体は失われません。

この記事では、git addを取り消す(unstage)方法を状況別に整理します。Git 2.23以降の推奨コマンドgit restore --staged、昔から使われているgit reset、ファイルの一部(ハンク単位)だけ戻す方法、git addだけでなくgit rmgit mvを取り消す場合まで実務で迷わない形で解説します。

この記事で学べること

  • Gitの3層構造(作業ツリー/index/HEAD)とaddが何をしているか
  • Git 2.23以降の推奨:git restore --staged <file>の使い方
  • 旧コマンドgit reset HEAD <file>との違いと互換性
  • 特定ファイルだけ/全ファイル/ハンク単位のunstage手順
  • 新規追加・削除・renameのaddを取り消す特殊ケース
  • よくある失敗(--hardとの混同、ファイル消失事故)の予防
  • GUI・IDE(VS Code/GitHub Desktop)でのunstage方法
スポンサーリンク

まず押さえる:git add は何をしているのか

「addの取り消し」を理解するには、Gitの3層構造を把握しておくと迷いません。

レイヤー 意味 操作コマンド
作業ツリー エディタで編集している実ファイル エディタ/vim
index(ステージング) 次のcommit候補を置く中間領域 git add / git rm --cached
HEAD(commit履歴) 確定済みのリポジトリ履歴 git commit

ポイント:git addは「作業ツリー → index」へ変更をコピーする操作です。add の取り消しとは、indexに入れた変更をHEADと同じ状態に戻すことを指します。作業ツリーのファイル内容は変わりません(残したまま戻します)ので、「addの取り消し=ファイルが消える」ではないことを意識してください。

取り消しパターン早見表

状況別に使うコマンドを整理しました。Git 2.23以降はgit restore --stagedが推奨、互換性のためgit reset系も記載しています。

状況 推奨(新) 旧コマンド
特定ファイルのaddを取り消す git restore --staged <file> git reset HEAD <file>
全ファイルのaddを取り消す git restore --staged . git reset HEAD(またはgit reset
ハンク(変更の一部)だけunstage git restore --staged -p <file> git reset -p HEAD <file>
新規追加(untracked)のaddを取り消す git restore --staged <newfile> git rm --cached <newfile>
削除/renameのaddを取り消す git restore --staged <file> git reset HEAD <file>

禁止コマンド:git reset --hardをaddの取り消しに使わないでください。ファイルの変更自体が失われます(未コミットの作業が全て消え、reflogにも残りません)。addの取り消しならgit restore --stagedまたはgit reset--hardなし)で十分です。

推奨:git restore –staged でaddを取り消す

Git 2.23で導入されたgit restoreはファイル復元専用コマンドで、--stagedオプションを付けるとindexから指定ファイルを取り消します。作業ツリーは触らないので、ステージだけを戻す本命コマンドです。

git restore –staged の基本
# 特定ファイルのaddを取り消す
git restore --staged config.py

# 複数ファイルを指定
git restore --staged src/auth.py src/utils.py

# ディレクトリ配下をまとめて
git restore --staged src/

# カレントディレクトリ以下すべて
git restore --staged .

# 状態を確認
git status
# → 「Changes not staged for commit」に戻っていればOK

restore –staged の挙動

  • indexをHEADの状態に戻す(commit済みファイルの場合)
  • 作業ツリーのファイル内容は変更しない
  • 未追跡だった新規ファイルのaddも取り消せる(indexから除外)
  • --worktreeを同時指定すると作業ツリーも戻すが、本記事の目的なら不要

全ファイルをまとめてunstage

すべてのaddを取り消す
# プロジェクト全体のaddを取り消す
git restore --staged .

# または旧コマンドでも等価
git reset HEAD
git reset   # 引数なしで全unstage(--mixedが既定)

旧来:git reset でaddを取り消す

Git 2.23以前はgit reset HEAD <file>が標準でした。機能的にはgit restore --stagedと同等で、既存のチュートリアルやスクリプトでも広く使われています。新規に書くならrestore推奨ですが、古い環境や既存の手順書ではresetのままでも問題ありません。

git reset での取り消し
# 特定ファイルをunstage(--mixedが既定)
git reset HEAD config.py
# 実はHEADは省略可能
git reset config.py

# 全ファイルをunstage
git reset
git reset HEAD   # HEAD明示も可

# ディレクトリ配下をまとめて
git reset HEAD src/

注意:git reset <file>引数にファイルを指定すると、--mixed--soft--hardのオプションは無視されます。ファイル指定のresetは「そのファイルのindexだけ戻す」動作になり、作業ツリーは触られません。この仕様があるため、git reset --hard <file>と書いても--hardは意味を持ちません(幸い)。

ブランチ全体を戻すresetとの違い

reset のモード別整理

  • git reset <file>:ファイル指定 → そのファイルのindexを戻すだけ(本記事の用途)
  • git reset --mixed <SHA>:ファイル未指定 → HEAD移動+indexリセット
  • git reset --soft <SHA>:HEAD移動のみ(ステージ保持)
  • git reset --hard <SHA>:作業ツリーも破棄(危険

reset全般の詳細は特定のコミットまで戻す方法revertとresetの違いと使い分けも参考になります。

ハンク単位でaddを取り消す(-p)

1つのファイルをgit addしたが、「このハンクはステージから外したい」と後悔することがあります。-p(patchモード)で変更の塊(ハンク)単位で取り消しを選べます。

ハンク単位のunstage
# ハンクごとにunstageするか質問される
git restore --staged -p config.py

# 旧コマンド
git reset -p HEAD config.py

# 実行後に y/n/s/e/? を入力
#   y → このハンクをunstage
#   n → このハンクはそのまま
#   s → ハンクをさらに細かく分割
#   e → エディタで手動編集
#   q → 中止
#   ? → ヘルプ表示

ポイント:インタラクティブに選べるので「addしすぎた変更のうち、特定の修正だけ外す」が可能になります。逆の操作(add したい変更を選びながらステージ)はgit add -p。コミットを細かく分けたいとき、この-pは強力な味方です。

新規追加ファイルのaddを取り消す特殊ケース

未追跡(untracked)だった新規ファイルをaddした場合、取り消すとそのファイルは元の「untracked状態」に戻ります。ファイル自体は作業ツリーに残り、削除はされません。

新規ファイルのunstage
# 新規作成したファイルをaddしてしまった
touch new_feature.py
git add new_feature.py
git status
# → "new file: new_feature.py" が Changes to be committed に表示

# Git 2.23以降(推奨)
git restore --staged new_feature.py
# → untrackedに戻る(ファイル自体は残る)

# 旧コマンド版
git rm --cached new_feature.py
# → 同じくuntracked に戻す

git restore –staged と git rm –cached の違い

  • 新規addの取り消し:どちらも結果は同じ(untracked状態に戻る)
  • 既にtrackedなファイルgit rm --cachedは追跡自体を解除する強い操作でcommitすると他メンバーからファイルが消える。単なるunstageならgit restore --stagedgit reset HEADを使う
  • 追跡自体を外したい場合は管理からファイルを外す方法を参照

削除・renameをaddしたときの取り消し

git rmで削除をステージした、git mvでrenameをステージした——これらも「add同様の操作」として扱われるため、同じコマンドで取り消せます。

削除・renameの取り消し
# 削除をステージしたあと(git rm や rm+git add)
git rm old_file.py
git status
# → "deleted: old_file.py" が Changes to be committed

# 取り消し(indexだけ戻す)
git restore --staged old_file.py
# → 作業ツリーには old_file.py は既にないため、さらに復元したい場合は
git restore old_file.py   # --worktreeも戻してファイル自体を復元

# renameをステージした場合
git mv oldname.py newname.py
git status
# → "renamed: oldname.py -> newname.py"

# 取り消し(両ファイル名とも指定して戻す)
git restore --staged oldname.py newname.py
# 作業ツリーも戻したい場合
git restore oldname.py newname.py

削除されたファイルの復元は消したファイルを戻す方法で詳しく解説しています。

実践シナリオ

シナリオ① git add . で余計なファイルまで混ざった

全部addしてしまってから選び直す
# 状態確認
git status

# 全部unstage
git restore --staged .

# 本当にcommitしたいファイルだけを個別にadd
git add src/feature.py src/utils.py

# 残りは.gitignoreやskipworktreeで対応
git commit -m "feat: 新機能を追加"

シナリオ② 機密情報を含むファイルを間違えてadd した

機密ファイルを即unstage
# すぐにindexから外す
git restore --staged .env

# 今後の事故防止のため.gitignore追記
echo ".env" >> .gitignore
git add .gitignore

# 機密ファイルが除かれたことを再確認
git status
# → .env が Changes not staged for commit 側に移動していればOK

注意:addしただけなら取り消しで済みますが、commit+push済みの場合はrotate最優先+履歴書き換えが必要です。履歴に含まれる機密情報を完全に削除する方法pushを取り消す方法を必ず確認してください。

シナリオ③ 1ファイル内の一部変更だけ残したい

ハンク単位で細かく調整
# ファイルのaddを一度全取り消し
git restore --staged src/api.py

# 必要な箇所だけ選びながらadd
git add -p src/api.py
# y/n/s/e で選択

# commit
git commit -m "fix: API認証の修正のみ"

# 残った変更は別コミットに
git add src/api.py
git commit -m "refactor: その他の整理"

シナリオ④ commit してしまった

addした後にcommitまで進んでしまった場合は「add取り消し」ではなく「commit取り消し」の領域です。

commit済みからaddを戻す
# 直前のcommitを取り消し、変更はindexに残す
git reset --soft HEAD~1

# さらにindexから外して作業ツリーへ
git restore --staged .

# 必要なファイルだけ選び直してadd&commit
git add src/feature.py
git commit -m "feat: 本来入れたかった変更だけを再コミット"

commit取り消しの詳細はコミットの取り消し方を参照してください。

GUI・IDEでのunstage方法

コマンドラインが苦手ならIDEのGUI操作でも同じことができます。

主要ツールでのunstage

  • VS Code / Cursor:Source Controlパネルで「Staged Changes」の各ファイル横のマイナスボタン、または右クリック→Unstage Changes
  • GitHub Desktop:左のChangesリストでチェックを外すだけ(次回commitに含めない扱い)
  • JetBrains(IntelliJ/WebStorm):Commit Windowで「Unversioned Files」と「Default Changelist」の間でドラッグ、または右クリック→Unstage
  • SourceTree:Staged filesパネルでファイルを選択しUnstageボタン
  • gitk –all:コマンドライン寄りの視覚化、unstageはgit guiを併用

ポイント:GUIでunstageしても内部的にはgit restore --stagedgit reset HEADが呼ばれています。操作感が分かりやすいので新人メンバーや「一部だけ選ぶ」場面にはGUIが向いています。

やってはいけない落とし穴

git reset –hard でaddを取り消そうとする

git reset --hardはコミット単位の戻し方であり、ファイルを指定せずに実行すると作業ツリーの未コミット変更すべてを破棄します。addを取り消したいだけならgit restore --staged <file>またはgit reset HEAD <file>で十分です。--hardで消えた変更はreflogにも残らないため、復元は不可能です。

git rm で取り消そうとして実ファイルも消す

git rm <file>--cachedなし)は作業ツリーのファイルも削除します。add の取り消しではなく「ファイル削除をステージ」という別の操作です。未追跡ファイルのaddを取り消すならgit rm --cached <file>またはgit restore --staged <file>を使ってください。

revert で add を取り消そうとする

旧記事でもよく見る誤解ですが、git revertコミット済みの変更を打ち消すコマンドで、「addの取り消し」には使いません。addはまだコミット前の段階なので、そもそもrevertの対象になりません。コミット後ならrevertreset --soft HEAD~1を使い分けます。詳しくはコミットの取り消し方を参照。

git reset と git reset HEAD の違いを取り違える

git reset(引数なし)は「全ファイルをunstage」、git reset HEADも同じ挙動、git reset HEAD <file>は「指定ファイルだけunstage」、git reset HEAD~1は「直前のコミットを取り消し」と、引数によって意味が変わります。「ファイル名を付けたかどうか」で挙動が全く異なる点に注意してください。

addの取り消しで作業ツリーも戻したつもりになる

git restore --staged <file>はあくまで「indexを戻す」だけで、作業ツリーのファイル内容は変えません。「編集自体も取り消したい」ならgit restore <file>--worktree側)を別途実行するか、git restore --staged --worktree <file>で同時処理します。後者はファイル内容も巻き戻す破壊的操作なので、編集の消失リスクを理解して使ってください。

よくある質問

Qgit restore –staged と git reset HEAD、どっち使えばいい?
AGit 2.23以降の環境ならgit restore --stagedが推奨です。ファイル復元専用で誤操作が起きにくいためです。古いGitや既存スクリプトではgit reset HEADのままで問題ありません。機能は同じです。
Qgit add . で大量addしてしまった。全部取り消すには?
Agit restore --staged .またはgit reset(引数なし)で全ファイルのaddを取り消せます。作業ツリーのファイル変更はそのまま残るので、必要な分だけ選び直してaddし直せます。
Qaddを取り消すとファイルの変更内容は消える?
A消えません。git restore --stagedgit reset HEADも「indexを戻すだけ」で作業ツリーは触らないため、ファイルの編集内容は保持されます。安心して実行できます。
Qハンク単位の細かい取り消しはできる?
Agit restore --staged -p <file>またはgit reset -p HEAD <file>でインタラクティブに選べます。y/n/sで各ハンクの取り扱いを決められ、コミットを細かく分けたいときに便利です。
Qコミットしてしまった後にaddを戻したい
Agit reset --soft HEAD~1で直前のcommitを取り消し、変更をindexに戻します。その後git restore --staged .でaddも取り消せば、作業ツリーに変更が残った状態に戻れます。詳細はコミットの取り消し方も参照。
Qaddしてpushまでしてしまった
A「add取り消し」ではなく「push取り消し」の領域です。共有ブランチならgit revertで打ち消しコミットを追加するのが安全です。pushを取り消す方法を参照してください。
QVS Codeでunstageしたら戻せる?
ASource Controlパネルでファイル横のマイナスボタン、または右クリック→「Unstage Changes」を使います。内部的にはgit restore --stagedが実行されているだけなので、ファイル内容は変わらず安心です。

関連記事

まとめ

  • addの取り消しはindexを戻すだけ——作業ツリーの変更は消えない安全な操作
  • Git 2.23以降の推奨:git restore --staged <file>
  • 旧コマンド:git reset HEAD <file>(機能は同じ)
  • 全ファイル一括ならgit restore --staged .またはgit reset
  • ハンク単位は-pオプションで選択的にunstage
  • 新規ファイルはrestore --stagedrm --cachedでuntrackedに戻せる
  • git reset --hardは絶対に使わない——ファイルの変更が失われる
  • コミット後なら「commit取り消し」、push後なら「push取り消し」の領域へ

addの取り消しは、Gitの3層構造(作業ツリー/index/HEAD)を理解していれば怖くない操作です。indexはHEADと作業ツリーの間のただの「仮置き場」であり、仮置きしたものを戻すだけなので失敗してもやり直せます。GUIツール・git add -prestore --stagedを使い分けて、きれいな粒度でコミットを組み立てる習慣を付けましょう。それがレビューしやすく、後から履歴を読み返しやすい、質の高いGit運用への第一歩です。