
【Git初心者向け】もう怖くない!git stash, reset, bisectでミスを帳消し&原因特定する実践テクニック
開発歴10年以上の現役エンジニアの管理人がGitを使い始めたばかりの頃、
git reset --hardで大事な変更を消してしまい、半日かけて復旧作業をした苦い経験があります。そんな「やらかし」は、もうあなたには経験してほしくありません。
あなたもGitを使った開発で、こんな経験はありませんか?
- コミットした直後に、含めるべきでなかったファイルやtypoに気づいた…
- 機能開発の途中で、緊急のバグ修正依頼が舞い込んできて、頭が真っ白になった…
- 「昨日までは動いていたのに…」いつの間にか紛れ込んだバグ。数十個のコミットから原因を探すのは骨が折れる…
大丈夫です!この記事で紹介するgit stash, git reset, git bisectという3つのコマンドは、そんな「困った!」を解決するための強力な武器になります。
この記事を読み終える頃には、あなたはまるで時間を操るようにGitの履歴を整理し、ミスを恐れず、自信を持って開発を進められるようになっているでしょう!
目次
対象読者
本記事は、以下のような方を対象としています。
- Gitの基本的な操作(
add,commit,push)は覚えた、次のステップに進みたい方 - 作業の中断やコミットの取り消しといった、実践的な操作にまだ自信がない方
- 開発中に発生したバグの原因を、効率的に特定する方法を知りたい方
操作の概要
スタッシュ (stash): 「ちょっと待って!」という時に。
コミットはしたくないけれど、急用でブランチを切り替えたい。そんな時、やりかけの作業を一時的に「スタッシュ」に退避させて、作業ディレクトリを綺麗な状態に戻します。用事が済んだら、隠した作業を元通りに復元できます。
リセット (reset): 「今の、なし!」という時に。
直前のコミットに間違いを見つけた時など、コミットそのものを取り消して、過去の状態に戻るコマンドです。非常に強力ですが、歴史を書き換えるため、使い方には細心の注意が必要です。
バイセクト (bisect): 「原因は何処だ!」という時に。
いつの間にか発生したバグの原因が、どのコミットにあるのかを特定するためのデバッグツールです。Gitが「探偵」のように質問を繰り返して、原因となったコミットを自動で絞り込んでくれます。
コマンド別:使い方と利用シーン
1. git stash:作業の一時退避
概要
まだコミットしたくない変更を、一時的に退避させるためのコマンドです。作業ディレクトリとステージングエリアの変更を「スタッシュ(隠し場所)」に保存することで、ブランチをクリーンな状態に戻せます。これにより、現在の作業をコミットすることなく、別のブランチに切り替えて作業を続けることが可能になります。

利用シーン
機能Aの開発中に、緊急のバグ修正依頼が来た。Aの作業は中途半端でコミットしたくないが、バグ修正のためにブランチを切り替えたい。
実行手順
- 作業の途中で、変更が残っている状態だとします。
git stashまたはgit stash push -m "メモ"を実行して、現在の変更を退避させます。
# メッセージを付けてスタッシュする
$ git stash push -m "ユーザープロフィール画面の途中"実行後、git status を見ると、作業ディレクトリが、直前のコミットの状態に戻っていることがわかります。
- これで心置きなくブランチを切り替え、緊急の作業を行えます。
# hotfixブランチに切り替える
$ git switch hotfix-branch
# ... バグ修正作業 ...- 用事が済んだら、元のブランチに戻ります。
# 元のfeature/a-branchブランチに戻る
$ git switch feature/a-branchgit stash listで退避させた作業の一覧を確認します。
stash@{0}: On feature/a-branch: ユーザープロフィール画面の途中git stash popを実行して、退避させた作業を復元します。
# 最新のスタッシュを復元し、スタックから削除する
$ git stash poppopは、復元と同時に退避リストからその内容を削除します。復元後もリストに残したい場合は git stash apply を使います。
コマンドの実行例:スタッシュを使った待避と復元
# feature/a-branchで作業中(index.htmlを編集中)
$ git status
On branch feature/a-branch
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: index.html
no changes added to commit (use "git add" and/or "git commit -a")
# バグが発生したので、作業状態を待避
$ git stash push -m "ホーム画面の途中"
Saved working directory and index state On feature/a-branch: ホーム画面の途中
# 待避した内容を確認
$ git stash list
stash@{0}: On feature/a-branch: ホーム画面の途中
# スタッシュしたファイルがないことを確認
$ git status
On branch feature/a-branch
nothing to commit, working tree clean
# hotfix-branchをmainブランチをベースに作成
$ git branch hotfix-branch main
# hotifx-branchでの作業完了
... 中略
# 元のブランチに戻る
$ git switch feature/a-branch
# スタッシュしたファイルを復元する
$ git stash pop
On branch feature/a-branch
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: index.html
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (2895c22c7b5e3fc8e4c7f350477e9cc9e02d9b7d)
# git statusでも確認
$ git status
On branch feature/a-branch
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: index.html
no changes added to commit (use "git add" and/or "git commit -a")2. git reset:コミットの取り消しと履歴の書き換え
概要
ブランチのHEADを指定した過去のコミットまで移動させることで、コミットを取り消すコマンドです。オプションによって、取り消したコミットの変更をどのように扱うかが異なります。
- 【重要】
resetvsrevert:歴史を「書き換える」か「打ち消す」かgit resetはコミット履歴そのものを書き換える(消し去る)破壊的な操作です。そのため、リモートリポジトリにプッシュしてチームで共有済みのコミットに対しては、原則として使用してはいけません。 もし共有済みの歴史を書き換えてしまうと、他のチームメンバーのリポジトリと深刻なコンフリクトを引き起こす原因となります。 一方、git revertは、指定したコミットの変更内容を打ち消す新しいコミットを作成します。履歴は書き換えず、過去の過ちを正すための新たな歴史を追加する、安全な方法です。git reset: まだプッシュしていない、自分のローカルリポジトリだけのコミットを整理したい時に使う。git revert: すでにプッシュしてしまったコミットの間違いを、安全に修正したい時に使う。
git reset --soft HEAD~1
概要: 直前のコミットを1つだけ取り消しますが、変更内容はステージングエリアに残します。
利用事例:
- コミットメッセージを間違えた。
- コミットに含めるのを忘れたファイルがあった。
実行手順:
# 直前のコミットを取り消し、変更をステージングエリアに残す
$ git reset --soft HEAD~1この後、ファイルを追加したり、正しいメッセージで再度コミット (git commit -m "正しいメッセージ") し直すことができます。
git reset --mixed HEAD~1 (デフォルト)
概要: 直前のコミットを1つ取り消し、変更内容をワーキングツリーに残します。ステージングエリアはリセットされます。これはresetコマンドのデフォルトの動作です。
利用事例:
- 直前のコミットの内容を、ステージングされる前の状態に戻して、もう一度変更内容を練り直したい。
- コミットを再構成(一部の変更だけ採用するなど)したい。
実行手順:
# 直前のコミットを取り消し、変更をワーキングツリーに残す
# --mixedはデフォルトなので省略可能
$ git reset HEAD~1この後、git status を見ると、コミットされる前に戻った変更が「Changes not staged for commit」として表示されます。ここから必要なファイルだけを git add し直して、新しいコミットを作成できます。
git reset --hard HEAD~1
概要:
直前のコミットを1つ取り消し、さらにそのコミットに含まれるすべての変更内容を作業ディレクトリとステージングエリアから完全に削除します。
利用事例:
- お試しで加えてみた変更が全く不要になったので、コミットごと綺麗さっぱり消したい。
実行手順:
# (危険) 直前のコミットと、その変更内容を完全に削除する
$ git reset --hard HEAD~1【警告】
このコマンドで消えた変更は、基本的には元に戻せません。実行する前には、本当にその変更が不要か十分に確認してください。
【最後の命綱:reflog】
万が一、必要な変更を--hardで消してしまった場合でも、git reflogコマンドで過去の操作履歴を確認し、特定の時点に復元できる可能性があります。これは最後の手段として覚えておきましょう。
3. git bisect:二分探索によるバグの特定
概要
「いつの間にかバグが入り込んでしまったけど、どのコミットが原因か分からない…」そんな時に、Gitが探偵のように犯人(バグの原因となったコミット)を見つける手伝いをしてくれるコマンドです。
利用シーン
- 「昨日は動いていたのに、今日は動かない。この数十個のコミットのうち、どれが原因だろう?」という状況。

実行手順
git bisect startで、特定プロセスを開始します。git bisect badで、現在のコミット(バグがある状態)を「悪い」とマークします。git logなどで正常に動作していたコミットIDを調べ、git bisect good <コミットID>で「良い」とマークします。
# bisectセッションを開始
$ git bisect start
# 現在のコミットを"bad"(問題あり)とマーク
$ git bisect bad
# 正常だったことが分かっているコミット(ハッシュ値は例)を"good"(問題なし)とマーク
$ git bisect good f4a1b2c- Gitは自動で範囲内の中間地点のコミットに移動します。ここで、プログラムの動作を確認します。
- もしバグが再現したら
git bisect badを実行。 - もしバグが再現しなければ
git bisect goodを実行。
- 上記4.を何度か繰り返すと、Gitが自動で範囲を半分に狭めていき、最終的に「このコミットが最初にバグを発生させた」と原因のコミットを突き止めてくれます。
- 調査が終わったら、
git bisect resetで元の状態に戻ります。
参考資料
- Pro Git Book – Git のさまざまなツール (スタッシュ、リセット)
- Git公式ドキュメント
まとめ:ミスを恐れず、Gitを使いこなそう
今回は、Gitを使った開発でよくある「困った!」を解決する、以下の3つのコマンドを解説しました。
git stash: 急な割り込み作業が来ても、やりかけの仕事を安全に一時退避できる「魔法のポケット」。git reset: ローカルでのコミットミスを、綺麗にやり直せる「タイムマシン」。ただし、共有履歴には使わないこと。git bisect: バグの原因となったコミットを、Git探偵が自動で特定してくれる「強力なデバッグツール」。
これらのコマンドは、あなたの開発ワークフローをより安全で、効率的なものに変えてくれます。特にresetとrevertの違いをしっかり理解し、適切な場面で使い分けることができれば、もうGitの操作は怖くありません。
この記事が役に立ったと感じたら、ぜひSNSでシェアしていただけると嬉しいです!
本記事をご利用いただくにあたって
この記事は、公開時点(2025年9月)の情報に基づき、正確な情報を提供するよう努めています。
しかし、本記事で解説するソフトウェアやサービスの仕様は日々更新されるため、記事内で紹介している画面や手順が、ご覧いただいている時点では変更されている可能性があります。
もし内容に相違がある場合は、各サービスの最新の公式ドキュメントも併せてご参照ください。本記事の情報を利用される際は、ご自身の判断と責任においてお願いいたします。





