revertとreset
取消しの目的に応じて、履歴・ステージ・作業ファイルのどこが変わるかを説明します。
説明
変更を取り消すときは、共有する履歴に取消しを記録したいのか、手元の参照や未記録の編集を戻したいのかを先に決めます。revertは逆向きの変更を新しいコミットにし、resetは現在のブランチやステージ、作業ファイルを指定した状態へ戻します。
設定値10→20→30の三つのコミットから始めます。30をrevertした後、元の30を指すsavedタグから別ブランチを作り、HEADが30・ステージが40・作業ファイルが50という状態でresetの各モードを実行します。
取消しの目的に応じて、履歴・ステージ・作業ファイルのどこが変わるかを説明します。
1戻す前の履歴を確認
現在の設定は30です。savedタグも同じコミットを指しています。
git log --oneline --decorate元の履歴とsavedの位置を確認する
cat settings.ini現在の設定を読む10、20、30を別々に記録した履歴があります。ここから30への変更を取り消す方法を確認します。
2revertは取消しのコミットを追加する
直近の30への変更をrevertします。--no-editは自動生成されたメッセージを使う指定です。
git revert --no-edit HEAD直近の変更を打ち消すコミットを作る
git log -2取消しと元のコミットを読む --format="%h parent=%p %s"
cat settings.ini設定は20に戻りましたが、30のコミットは親として履歴に残っています。取り消した事実を新しいコミットとして共有できる形です。
3元の30から別の作業状態を作る
savedからreset-caseブランチを作ります。40をステージに入れた後、作業ファイルだけ50へ変えます。
git switch -q -c reset-case saved元の30から比較用のブランチを作る
printf 'timeout=40\n' > settings.ini
git add settings.ini40をステージへ入れる
printf 'timeout=50\n'作業ファイルだけ50へ変える > settings.ini
printf 'untracked note\n' > notes.txt
git status --short設定はMMです。HEADの30、ステージの40、作業ファイルの50が異なります。notes.txtはまだ追跡されていない独立したファイルです。
4softはHEADだけを戻す
HEADの親、つまり20のコミットへsoft resetします。三つの内容を読みます。
git reset --soft HEAD^ブランチの参照先だけを親へ戻す
git show HEAD:settings.ini
git show :settings.iniステージの内容を読む
cat settings.iniHEADは20、ステージ40、作業ファイル50です。softはステージと作業ファイルを保持するため、これまでの変更をまとめ直す起点として使えます。
5mixedはステージも合わせる
現在のHEADである20へmixed resetします。参照先は同じまま、ステージを20へそろえます。
git reset --mixed HEADHEADの内容をステージにも反映する
git show HEAD:settings.ini
git show :settings.ini
cat settings.ini
git status --short未ステージの編集として残ることを確認するHEAD20・ステージ20・作業ファイル50です。設定のMは右側だけになります。mixedは既定のresetモードですが、ここでは操作範囲を明示しています。
6hardは作業ファイルも書き換える
今度は作業ファイルの50を破棄し、現在のHEADの20へそろえます。この操作では未コミットの編集が失われます。
git reset --hard HEAD参照・ステージ・作業ファイルをHEADへそろえる
git show HEAD:settings.ini
git show :settings.ini
cat settings.ini
git status --short残った未追跡ファイルを確認する三つとも20になり、設定のMは消えました。この例のnotes.txtは書込み先を妨げないため残ります。hard resetは追跡対象の作業内容を書き換え、妨げになる未追跡ファイルも削除する場合があります。
7記録済みの30は別の参照から読める
savedタグから元の30を読み、参照の移動記録を確認します。
git show saved:settings.ini別の参照が保持する元の内容
git reflog -5最近のHEADの移動を表示する --format="%h %gs"30のコミットはsavedから参照できます。reflogにはresetや切替えが残りますが、未コミットの作業ファイルの全内容を保存する機能ではありません。失った50がここから戻せるとは限りません。
8元のコミットにブランチ名を付ける
savedの位置にrecoveredブランチを作ります。現在のreset-caseは切り替えません。
git branch recovered saved元のコミットを指すブランチを作る
git rev-parse --short recovered
git symbolic-ref HEAD作業ブランチが変わっていないことを確認する
cat settings.inirecoveredは30を指し、現在の作業ファイルは20のままです。参照名を作る操作と、作業内容をそのコミットへ切り替える操作は別です。
9同じ20でも履歴は異なる
revertしたmainとreset-caseで、現在値と到達可能なコミット数を比較します。
git show main:settings.inirevert後の値
git show reset-case:settings.inireset後の値
git rev-list --count各参照からたどれるコミット数 main
git rev-list --count reset-caseどちらも20ですが、mainは取消しを含む4コミット、reset-caseは2コミットです。内容が同じでも、変更と取消しの記録を残したかどうかが異なります。
まとめ
revertは逆向きの変更を新しいコミットにし、元の変更と取消しの履歴を残します。
reset --softは参照、--mixedはステージまで、--hardは作業ファイルまで戻します。
記録済みのコミットを参照し直すことと、未コミットの編集を復旧することは別です。操作範囲を確認してから取り消します。
操作履歴と解説を振り返れます。
Git / シェル
git log --oneline --decorate
cat settings.inic7ba33e (HEAD -> main, tag: saved) Set timeout to 30 8939a78 Set timeout to 20 feb47f5 Initial files timeout=30
git revert --no-edit HEAD
git log -2 --format="%h parent=%p %s"
cat settings.ini[main 54909ca] Revert "Set timeout to 30" Date: Sun Nov 1 09:00:00 2026 +0900 1 file changed, 1 insertion(+), 1 deletion(-) 54909ca parent=c7ba33e Revert "Set timeout to 30" c7ba33e parent=8939a78 Set timeout to 30 timeout=20
git switch -q -c reset-case saved
printf 'timeout=40\n' > settings.ini
git add settings.ini
printf 'timeout=50\n' > settings.ini
printf 'untracked note\n' > notes.txt
git status --shortMM settings.ini ?? notes.txt
git reset --soft HEAD^
git show HEAD:settings.ini
git show :settings.ini
cat settings.initimeout=20 timeout=40 timeout=50
git reset --mixed HEAD
git show HEAD:settings.ini
git show :settings.ini
cat settings.ini
git status --shortUnstaged changes after reset: M settings.ini timeout=20 timeout=20 timeout=50 M settings.ini ?? notes.txt
git reset --hard HEAD
git show HEAD:settings.ini
git show :settings.ini
cat settings.ini
git status --shortHEAD is now at 8939a78 Set timeout to 20 timeout=20 timeout=20 timeout=20 ?? notes.txt
git show saved:settings.ini
git reflog -5 --format="%h %gs"timeout=30 8939a78 reset: moving to HEAD 8939a78 reset: moving to HEAD 8939a78 reset: moving to HEAD^ c7ba33e checkout: moving from main to reset-case 54909ca revert: Revert "Set timeout to 30"
git branch recovered saved
git rev-parse --short recovered
git symbolic-ref HEAD
cat settings.inic7ba33e refs/heads/reset-case timeout=20
git show main:settings.ini
git show reset-case:settings.ini
git rev-list --count main
git rev-list --count reset-casetimeout=20 timeout=20 4 2
演習完了