🐧 Linux 総合学習プラットフォーム
Git バージョン管理 ・ 中級

取り消し操作の基本(restore / reset)

Gitでは操作を取り消す方法が状況ごとに分かれています。作業ツリーの編集を捨てて元に戻すには git restore、ステージに載せた変更を下ろす(ステージから外す)には git restore --staged を使います。直前のコミットを取り消して変更を作業ツリーに戻したいときは git reset を使いますが、履歴を巻き戻す操作なので慎重に扱います。まずは「どの段階を取り消したいのか」を見極めることが大切です。

Git の本当の価値は、「安心して戻せる」ことにある。間違えてもやり直せると分かっていれば、思い切って編集や実験ができる。

ただし Git では、ひとつの「戻す」で済むわけではない。「どの領域を・どこまで戻したいか」によって使うコマンドが変わるからだ。

💡
ポイント「戻す」は1つではない。どの領域を・どこまで戻したいかで、git restore・git commit --amend・git reset・git revert を使い分ける。

作業ツリーの編集だけを捨てたいのか、ステージング(git-staging)に載せたものを降ろしたいのか、確定したコミット(git-commit)そのものを巻き戻したいのか。目的が違えば手段も違う。

やみくもに強力なコマンドを使うと、取り返しのつかない事故につながることもある。そこでまず大切なのは、「いま自分はどの段階を取り消したいのか」を見極めることだ。

作業ツリーの編集git restore編集を捨てる/add降ろす直前のコミットcommit --amend作り直すコミットを巻き戻すgit reset共有前向き共有済みを取消git revert履歴を残す左ほど軽い取り消し、右ほど重い取り消し

順に、軽い取り消しから重い取り消しへと整理して覚えていこう。

↩ 編集を捨てる・add を降ろす git restore

いちばん身近な取り消しが git restore だ。これには2つの使い方があり、どちらも理解しておくと混乱しない。

1つ目はファイル名だけを指定する形だ。git restore readme.txt とすると、そのファイルに加えた「まだ add していない編集」を捨てて、最後のコミットの状態に戻す。

git restore readme.txt で未 add の編集を捨てる。git restore --staged readme.txt なら中身は残してステージから降ろすだけ。

たとえば echo 'mistake!!!' >> readme.txt と誤って書き足してしまっても、git restore readme.txt を打てば、その編集はなかったことになる。実行後に git diff を打って何も表示されなければ、元の状態に戻っている証拠だ。

2つ目は --staged を付ける形だ。git restore --staged readme.txt とすると、git add でステージに載せた変更を、中身はそのまま残してステージから降ろすだけにする。つまり「add の取り消し」だ。

つまずきファイル名だけの restore は編集内容そのものを捨てる破壊的な操作。本当に要らないと確信できるときだけ使う。迷ったら git status で案内を見る。

ここがポイントだ。ファイル名だけの restore は編集内容そのものを捨ててしまうのに対し、--staged を付けたほうは編集した中身は手元に残し、ステージから外すだけなので安全だ。

前者は捨てた編集が戻らない破壊的な操作なので、本当に要らないと確信できるときだけ使ってほしい。どちらを使うか迷ったら、まず git status を見れば、いまファイルがどの段階にあり、どう取り消せるかの案内が出ている。

🔧 直前のコミットを作り直す git commit --amend

「コミットした直後にメッセージの打ち間違いに気づいた」「1ファイル add し忘れたままコミットしてしまった」。こんなときに新しいコミットを足す必要はない。git commit --amend で直前のコミットを作り直せる。

git commit --amend -m 'Add third line' ……直前のコミットを置き換える。add し忘れたファイルは git add してから --amend すれば含め直せる。

たとえばメッセージを 'Add thrid line' と打ち間違えたら、git commit --amend -m 'Add third line' とすれば正しいメッセージに直せる。

--amend は新しいコミットを増やすのではなく、直前の1つを置き換える(その結果ハッシュは変わる)。ファイルを add し忘れていた場合も、そのファイルを git add してから --amend すれば、直前のコミットに含め直せる。

つまずき--amend はコミットを作り直す操作なので、すでに push して他人と共有したコミットには使わない。共有前の手元のコミットを整えるときに使う。

ただし注意点がある。--amend はコミットを「作り直す」操作なので、すでに push して他人と共有したコミットには使わないのが原則だ。まだ手元にしかない、共有前のコミットを整えるときに使ってほしい。

⏪ コミットごと巻き戻す git reset

コミットそのものを巻き戻したいときは git reset を使う。

reset は HEAD(git-head、現在の基準位置)を過去のコミットへ移して履歴を巻き戻す操作だ。このとき作業ツリーとステージングをどう扱うかで3つのモードがある。

git reset の3モード(どこまで巻き戻すか)--soft履歴だけ戻す変更はステージに残るコミットし直したいとき--mixed(既定)コミットとステージを取消編集は作業ツリーに残る--hardすべて巻き戻す編集内容も消える破壊的・要注意

--soft は履歴だけ戻し、変更はステージに残す(コミットし直したいとき向き)。既定の --mixed はコミットとステージを取り消しつつ、編集内容は作業ツリーに残す。--hard は履歴・ステージ・作業ツリーのすべてを巻き戻し、編集内容も消してしまう。

git reset --soft HEAD~1 ……HEAD~1 は「現在の1つ前のコミット」。最新のコミットだけ取り消して変更をステージに残す。

よく使う指定が HEAD~1 で、これは「現在の1つ前のコミット」を意味する。たとえば git reset --soft HEAD~1 は、最新のコミットだけを取り消して変更をステージに残すので、コミットをやり直したいときに便利だ。

☠ git reset --hard の危険

ここで一つ、強く意識してほしい危険がある。git reset --hard は手元の編集を問答無用で消す破壊的な操作だということだ。

つまずきgit reset --hard HEAD はステージも作業ツリーも巻き戻し、書き足した内容を跡形もなく消す。実行前にコミットとモードを二度確認する。

git reset --hard HEAD と打てば、ステージも作業ツリーも最新コミットの状態まで巻き戻り、それ以降に書き足した内容は跡形もなく消える。

実行する前に、対象のコミットとモード(とくに --hard かどうか)を二度確認する慎重さが必要だ。

コツ消したつもりのコミットも git reflog でしばらくは追える場合がある。ただし頼り切らず、reset は実行前に目で確かめる。

消したつもりのコミットも git reflog という記録でしばらくは追える場合があるが、それに頼り切るのは禁物だ。reset は強力なぶん、cli-basics で学んだ rm と同じく「実行前に目で確かめる」姿勢が効いてくる。

🔁 共有済みなら git revert

reset には大きな弱点がある。すでに push して他人と共有したコミットを reset で消すと、自分の履歴と他人の履歴が食い違い、深刻な事故につながる。

そこで、共有済みの変更を取り消したいときは git revert を使う。revert は過去のコミットを履歴から消すのではなく、「その変更を打ち消す新しいコミットを上に積む」操作だ。

git revert --no-edit HEAD ……直前のコミットを打ち消すコミットを新たに積む。--no-edit はメッセージ編集を省く指定。

たとえば git revert --no-edit HEAD とすると、直前のコミットの内容を打ち消すコミットが新たに作られ、「いつ何を取り消したか」も履歴として残る(--no-edit はメッセージ編集を省く指定)。

💡
ポイントreset は履歴を書き換えるので共有前の手元の整理に、revert は履歴を残すので共有済みの取り消しに向く。

整理すると、reset は履歴を書き換えるため、まだ共有していない手元の整理に向く。revert は履歴を残すため、共有済みの変更の取り消しに向く。

「まだ自分しか見ていないなら reset、もう共有したなら revert」と覚えておくと、取り消しで迷わなくなる。

この項目に出てくる用語

ステージングすてーじんぐ
コミット前に変更を載せておく準備エリア。インデックスとも呼ぶ。
コミットこみっと
変更を1つの履歴として確定する操作、またはその記録1件。
HEADへっど
いま自分が見ている(作業中の)コミットを指す印。

関連コマンド

git restoregit reset

▶ 学習アプリでこの続きを学ぶ・演習する