git stash は、まだコミットしていない変更をいったんしまい、作業ディレクトリをいまのコミット(HEAD)と同じきれいな状態に戻すコマンドです。しまった変更は git stash pop か git stash apply で戻せます。pop は戻したあとに一覧から消し、apply は一覧に残します。
この記事は、作業の途中で別のブランチに移りたくなった・急ぎの直しを頼まれた、という初心者に向けて、公式の文書(git-scm.com)に沿って使い方をまとめたものです。コマンドの出力は git 2.39.3(Apple Git-145・macOS)のものです。Git の表示は、日本語の環境でも英語で出ます(Git 本体に日本語の翻訳ファイルがありません)。
- git stash とは何か、どんなときに使うか
- 変更を退避する方法(メッセージ・未追跡のファイル・特定のファイル)
- pop と apply の違いと、コンフリクトしたときの直し方
- stash の消し方と、消してしまった stash の探し方
- save が非推奨になっていること(push を使う)
git stash とは?どんなときに使う?
公式の文書は、git stash を「作業ディレクトリとインデックス(git add した状態)のいまの状態は記録しておきたいが、作業ディレクトリはきれいな状態に戻したい」ときに使うコマンド、と説明しています。手元の変更をしまって、作業ディレクトリを HEAD のコミットと同じ状態に戻します。しまった変更は git stash list で一覧にし、git stash show で中身を見て、git stash apply で戻せます(別のコミットの上にも戻せます)。引数を付けない git stash は、git stash push と同じです。
使う場面の1つは、ブランチの切り替えです。ブランチは、変更が残っていても切り替えられることがあります。公式の文書(git switch)によると、切り替えが止まるのは、切り替えると手元の変更が失われるときだけです。移り先のブランチで中身が違うファイルに、まだコミットしていない変更があると、次のように止まります(git 2.39.3 の出力)。
$ git status --short
M a.txt
M b.txt
?? new.txt
$ git switch fix
error: Your local changes to the following files would be overwritten by checkout:
a.txt
Please commit your changes or stash them before you switch branches.
Aborting
このとき名前が出たのは、移り先で中身が違う a.txt だけでした。ここで git stash で変更をしまうと、ブランチを移れます。
$ git stash push -m "a と b を直している途中"
Saved working directory and index state On main: a と b を直している途中
$ git status --short
?? new.txt
$ git stash list
stash@{0}: On main: a と b を直している途中
$ git switch fix
Switched to branch 'fix'
?? new.txt は、Git がまだ追跡していない(まだ git add していない)ファイルです。未追跡のファイルは、オプションを付けないとしまわれず、作業ディレクトリに残ります(下の「未追跡のファイルも退避するには?」)。
公式の文書には「Interrupted workflow(作業の中断)」という例もあります。作業の途中で、すぐに直してほしいと頼まれたら、git stash でしまい、直してコミットし、git stash pop で作業に戻る、という流れです。
いちばん新しい stash は refs/stash に入り、古いものはその履歴(reflog)に並びます。stash@{0} がいちばん新しく、stash@{1} がその1つ前です。
変更を退避するには?(push とメッセージ)
git stash push は、手元の変更を新しい stash にしまい、作業ツリーとインデックスを HEAD の状態に戻します。メッセージは -m(--message)で付けます。付けないと、一覧には「WIP on <ブランチ名> …」と出ます(git 2.39.3 では、ブランチ名・HEAD の短いハッシュ・HEAD のコミットの件名が並びました)。
$ git stash push -m "b を直した"
Saved working directory and index state On main: b を直した
$ git stash
Saved working directory and index state WIP on main: 494d640 first
$ git stash list
stash@{0}: WIP on main: 494d640 first
stash@{1}: On main: b を直した
公式の文書は、作るときに、もっと分かりやすいメッセージを付けられる、と書いています。push は省いてもかまいません(git stash -m "…" でも動きます)。ただし省いたときは、ファイルの指定を -- のあとにしか書けません。打ち間違えたサブコマンドで、意図しない stash ができてしまうのを防ぐためです。
未追跡のファイルも退避するには?(-u)
新しく作って一度も git add していないファイル(未追跡のファイル)は、オプションを付けないとしまわれません。変更が未追跡のファイルだけのときは、git stash は何もしまわずに「No local changes to save」と出します。未追跡のファイルもしまうときは -u(--include-untracked)を付けます。しまったファイルは作業ディレクトリから消され(git clean されます)、pop で戻ります。
$ git status --short
?? new.txt
$ git stash
No local changes to save
$ git stash push -u -m "new.txt も退避"
Saved working directory and index state On main: new.txt も退避
$ git status --short
$ git stash show
$ git stash show -u
new.txt | 1 +
1 file changed, 1 insertion(+)
git stash show は、オプションを付けないと未追跡のファイルを出しません。-u を付けると一緒に出ます(--only-untracked なら未追跡のファイルだけ)。この表示のオプションは 2.32 からです。
.gitignore に書いて無視しているファイルは、-u でもしまわれません。無視しているファイルまでしまうのは -a(--all)です。.gitignore については .gitkeep と .gitignore の違いの記事で説明しています。
特定のファイルだけ退避するには?
git stash push のあとにファイル名を書くと、そのファイルの変更だけをしまい、そのファイルだけを HEAD の状態に戻します。ほかのファイルはそのままです。ファイルは複数書けます。push でファイルを指定できるようになったのは 2.13 からです。
$ git status --short
M a.txt
M b.txt
$ git stash push -m "a.txt だけ" a.txt
Saved working directory and index state On main: a.txt だけ
$ git status --short
M b.txt
気をつけたい3つ
git 2.39.3 では、次の3つが起きました。
git stash a.txtはエラーになる。pushを省いて、--を付けずにファイル名を書くと、何もしまわれません。git stash -- a.txtかgit stash push a.txtと書きます。git stash save a.txtは、全部しまってしまう。 save はファイルを指定できず、書いた文字はメッセージになります。下の例では、a.txtもb.txtもしまわれ、名前が「On main: a.txt」になりました。- 未追跡のファイルしか無いと「No local changes to save」と出る。 しまうなら
-uを付けます(上の節)。
$ git stash a.txt
fatal: subcommand wasn't specified; 'push' can't be assumed due to unexpected token 'a.txt'
$ git stash save a.txt
Saved working directory and index state On main: a.txt
$ git stash show
a.txt | 2 +-
b.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
退避した中身を確かめるには?(list・show)
git stash list は、いまある stash の一覧です。名前(stash@{0} がいちばん新しい)、作ったときのブランチ名、もとにしたコミットの短い説明が出ます。
git stash show は、stash に記録した変更を、stash を作ったときのコミットとの差分として出します。既定はファイルごとの増減(diffstat)で、-p を付けると変更の中身(パッチ)が出ます。古い stash を見るときは、git stash show -p stash@{1} のように名前を付けます。
$ git stash show
a.txt | 2 +-
b.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
$ git stash show -p
diff --git a/a.txt b/a.txt
index 83db48f..ca75c6e 100644
--- a/a.txt
+++ b/a.txt
@@ -1,3 +1,3 @@
line1
-line2
+line2 work in progress
line3
diff --git a/b.txt b/b.txt
index ce01362..3b18e51 100644
--- a/b.txt
+++ b/b.txt
@@ -1 +1 @@
-hello
+hello world
stash がいくつあるかは、git status --show-stash でも出せます(2.14 から)。git status の見方は、Git コマンドのよく使う使い方の記事でも紹介しています。
戻すには?pop と apply の違い
しまった変更を戻すコマンドは、pop と apply の2つです。
| pop | apply | |
|---|---|---|
| 戻したあとの stash | 一覧から消す | 一覧に残す |
| 戻せるもの | stash の一覧にあるもの | stash の一覧にあるもの・stash に見えるコミット(下の「stash を消すには?消してしまったら戻せる?」) |
| うまくいったときの最後の行 | Dropped refs/stash@{0} (…) と出る | 出ない |
どちらも、stash@{1} のように名前を書くとその stash を、書かないといちばん新しい stash@{0} を戻します。git stash pop 1 のように番号だけでも書けます(2.11 から)。
$ git stash apply
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git stash list
stash@{0}: WIP on main: 494d640 first
stash@{1}: On main: b を直した
$ git stash drop
Dropped refs/stash@{0} (55d368dd00aedeeb62a187c9e63b284410ef532f)
apply のあとも、一覧に stash@{0} が残っています。要らなくなったら git stash drop で消します。なお、git add してあった変更は、オプションを付けないと add していない状態で戻りました。add した状態ごと戻すときは --index を付けます(コンフリクトがあると失敗することがあります)。
コンフリクトしたら?pop しても stash は消えない
stash をしまったあとに、同じ所が別の内容でコミットされていると、pop がコンフリクト(同じ所の変更どうしがぶつかること)で止まることがあります。公式の文書によると、このとき stash は一覧から消えません。手でコンフリクトを直したあと、自分で git stash drop します。
$ git stash pop
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
On branch main
Unmerged paths:
(use "git restore --staged <file>..." to unstage)
(use "git add <file>..." to mark resolution)
both modified: a.txt
no changes added to commit (use "git add" and/or "git commit -a")
The stash entry is kept in case you need it again.
$ cat a.txt
line1
<<<<<<< Updated upstream
line2 committed
=======
line2 from stash
>>>>>>> Stashed changes
line3
最後の行の「The stash entry is kept in case you need it again.」は、stash を残したことを知らせる一文です。ファイルの中の印は、いまのブランチ側が「Updated upstream」、stash 側が「Stashed changes」です。どちらを残すかを決めて書き直したら、git add で解決済みにし、git stash drop で stash を消します。git 2.39.3 では、そのあと a.txt は add された状態(M a.txt)で残りました。git 2.39.3 では、コンフリクトが残ったまま、もう一度 pop すると「a.txt: needs merge」で止まり、stash は残りました。コンフリクトは、merge や rebase でも起きます(merge と rebase の違い)。
同じファイルに未コミットの変更があると、pop は始まらない
stash を戻す先のファイルに、まだコミットしていない変更があると、pop は当てる前に止まります。このときも stash は残ります(git 2.39.3 の出力)。
$ git stash pop
error: Your local changes to the following files would be overwritten by merge:
a.txt
Please commit your changes or stash them before you merge.
Aborting
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a.txt
no changes added to commit (use "git add" and/or "git commit -a")
The stash entry is kept in case you need it again.
うまく戻せないときは?(git stash branch)
git stash branch <ブランチ名> <stash> は、stash を作ったときのコミットから新しいブランチを作って移り、そこに stash を当てます。うまくいき、stash@{…} の形で指定していれば、その stash を消します。公式の文書は、stash を作ったあとで元のブランチが大きく変わり、apply がコンフリクトで失敗するときに役立つ、と書いています。stash を作ったときの HEAD の上に当てるので、コンフリクトせずに戻ります。
$ git stash branch from-stash "stash@{1}"
Switched to a new branch 'from-stash'
On branch from-stash
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a.txt
no changes added to commit (use "git add" and/or "git commit -a")
Dropped stash@{1} (0428582d08556b04ed43964fcc88e58e00831b31)
stash を消すには?消してしまったら戻せる?
git stash drop は stash を1つ消します。名前を書かないと stash@{0} を消します。1つ消すと、うしろの番号が詰まります(git 2.39.3 では、stash@{2} だったものが stash@{1} になりました)。git stash clear は stash を全部消します。git 2.39.3 では、確かめる問いは出ず、何も表示せずに一覧が空になりました。
注意: 公式の文書は、clear で消したものは掃除(prune)の対象になり、取り戻せないことがある、と書いています。消す前に git stash list と git stash show -p で中身を確かめましょう。
消してしまった stash を探す(公式の文書の方法)
公式の文書によると、間違えて drop・clear した stash は、ふつうの安全装置では戻せません。ただし、まだリポジトリに残っていて、どこからもたどれなくなった stash は、次のコマンドで一覧にできることがあります(文書では3行に分けて書かれています)。
git fsck --unreachable |
grep commit | cut -d\ -f3 |
xargs git log --merges --no-walk --grep=WIP
git fsck --unreachable は「あるが、どこからもたどれないオブジェクト」を出します。git log の --merges はマージコミットだけ、--no-walk は渡したコミットだけ(親をたどらない)、--grep はメッセージが合うものだけを出すオプションです。
見つかったコミットの名前を git stash apply に渡すと、中身が戻ります。apply は、stash に見えるコミットなら受け付けるからです(文書の例は一覧にするところまでで、apply に渡すのは apply の説明によるものです)。git 2.39.3 では、-u でしまった stash は、未追跡のファイルも戻りました。
$ git stash apply 786b6d00c2cf52eb44ef910993931da927ceea2d
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a.txt
no changes added to commit (use "git add" and/or "git commit -a")
注意: このコマンドは --grep=WIP でメッセージを絞るので、git 2.39.3 では、メッセージを付けずに作った stash(「WIP on …」)しか出ませんでした。-m でメッセージを付けた stash(「On main: …」)は、メッセージに WIP という文字が入っていない限り、この探し方では出てきません。stash ではない普通のコミットを apply に渡すと、「fatal: '669187b' is not a stash-like commit」のエラーになります。
pop・drop で表示された名前から戻す(git 2.39.3 の動き)
pop と drop は、最後に Dropped … (<名前>) と表示します。git 2.39.3 では、この名前は上のコマンドで見つかるコミットの名前と同じで、pop のあとで変更を捨ててしまったときも、この名前を git stash apply に渡すと戻りました。この使い方は、公式の文書には書かれていません。次の出力の git restore a.txt は、a.txt のまだコミットしていない変更を捨てるコマンドです。ここでは、変更を捨ててしまった場面を作るために流しています。
$ git stash pop
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a.txt
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (4d04822563dc808cc2a0dfdda8579bdb44fd8281)
$ git restore a.txt
$ git status --short
$ git stash apply 4d04822563dc808cc2a0dfdda8579bdb44fd8281
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a.txt
no changes added to commit (use "git add" and/or "git commit -a")
探せるのはいつまで?
git gc は、どこからもたどれない古いオブジェクトを消します。既定では2週間より古いものが対象で(gc.pruneExpire で変えられます)、git gc は、オブジェクトを作るふだんの操作のあとで、リポジトリが大きくなっていれば自動でも走ります。そのため、時間がたつと、消してしまった stash が見つからなくなることがあります。一方、一覧に残っている stash は、設定しない限り期限で消えません(1.6.0 の Release Notes とソースによる。git gc の文書は reflog の期限を既定 90 日とだけ書き、stash の例外には触れていません)。
git stash save はもう使わない?
公式の文書の言い回しは「This option is deprecated in favour of git stash push.」です。save は非推奨(deprecated)で、push を使うよう書かれています。非推奨になったのは 2.16 です。push と違って save はファイルを指定できず、オプションでない引数は全部つなげてメッセージになります(上の「気をつけたい3つ」の2つ目)。
ただし、save が使えなくなったわけではありません。最新の 2.56.0 の書式にも save は残っていて、git 2.39.3 では警告を出さずに動きました。Git 3.0 に向けた「互換性を壊す変更」の文書(BreakingChanges)にも、2026年10月時点で stash の語は出てきません。Pro Git(英語版)は、save はすぐには無くならないが、新しい機能のために push へ移るとよい、と書いています。おもな理由は、push はファイルを選んでしまえるが、save はできないことです。
新しい版で増えたものは?
2026年10月時点の最新の Git は 2.56.0(2026年9月28日公開)です。git-scm.com の git stash の文書は最新版の説明なので、古い Git では使えないものがあります。
| できること | 入った版 | git 2.39.3 では |
|---|---|---|
--staged(-S): add 済みの変更だけをしまう | 2.35 | 使える |
export・import: stash を書き出して、ふつうの fetch・push で運ぶ | 2.51 | 使えない |
設定 stash.index: apply と pop が --index を付けたのと同じに動く | 2.52 | 使えない |
--staged には公式の例があります。大きな作業の途中で関係のない直しを見つけたら、直して git add し、git stash push --staged で取っておく、というものです。
最後に、git stash の代わりになる道具も1つ紹介します。git worktree の公式の文書には、作業ツリーが散らかっていて触りたくないときは、git stash でしまう代わりに、一時的な作業フォルダ(worktree)を作って急ぎの直しをし、終わったら消す、という例があります。くわしくは git worktree とはの記事で説明しています。
よくある質問
別のブランチで作った stash を、いまのブランチで戻せる?
戻せます。公式の文書は、apply で別のコミットの上にも戻せる、と書いています。stash の一覧は1つなので、別のブランチで作った stash も一覧に「On feature: …」のように出ます。git 2.39.3 では、main で pop すると、main の上に戻りました。コンフリクトして戻しにくいときは、git stash branch で、stash を作ったときのコミットから新しいブランチを作って戻せます。
複数のファイルを指定して退避できる?
できます。git stash push a.txt b.txt のように、ファイルを並べて書きます(git 2.39.3 では、2つのファイルを指定してしまえました)。push を省くときは、git stash -- a.txt b.txt のように -- のあとに書きます。
stash した日時を見るには?
git stash list は git log のオプションを受け付けます。git 2.39.3 では、git stash list --date=iso や --date=local を付けると、番号の代わりに日時が出ました。
pop を強制したい(止まってしまう)
git stash の文書の書式には、pop・apply を強制するオプションはありません(2026年10月時点)。止まるのは、戻す先のファイルに未コミットの変更があるときや、コンフリクトしたときです。どちらの場合も stash は残っています。戻す先のファイルの未コミットの変更で止まったときは、表示のとおり、その変更をコミットするか、しまってから、もう一度 pop します。コンフリクトしたときは、手で直して git add し、git stash drop します(上の「コンフリクトしたら?」)。どちらの場合も、git stash branch で、stash を作ったときのコミットから戻す手もあります。
pop を取り消したい
pop を取り消して作業ツリーを元に戻す手順は、git stash の文書には書かれていません(2026年10月時点)。コンフリクトで止まったときは、stash は一覧に残っています。pop がうまくいって一覧から消えたあとでも、git 2.39.3 では、表示された Dropped … (<名前>) の名前を git stash apply に渡すと、もう一度当てられました(上の「pop・drop で表示された名前から戻す」)。
まとめ
- git stash は、まだコミットしていない変更をしまい、作業ディレクトリを HEAD の状態に戻すコマンド。引数なしの
git stashはgit stash pushと同じ - メッセージは
-m、未追跡のファイルもしまうなら-u、無視しているファイルまでなら-a。ファイルを指定するならgit stash push <ファイル>(push を省くなら--のあと) - pop は戻して一覧から消し、apply は一覧に残す。コンフリクトや未コミットの変更で止まったときは、stash は消えない
- 消した stash は、公式の文書のコマンドで探して apply で戻せることがある。ただし
-mを付けた stash はその探し方では出ず、掃除で消えることもある - save は非推奨(deprecated)。push を使うよう書かれている
参考資料
- git-stash(Git 公式の文書)
- git-switch(Git 公式の文書)
- git-gc(Git 公式の文書)
- git-worktree(Git 公式の文書)の EXAMPLES
- Pro Git 第2版(英語)Stashing and Cleaning
- Git 2.16.0 の Release Notes(save の非推奨)
- Git の公式サイト(最新の版)
※この記事は、公式の資料をもとに AI(Claude)で下書きし、2026年10月3日時点の公式の資料と照らして確かめてから公開しています。誤りに気づいたらお問い合わせからお知らせください。


