一覧SE-04-3 · Gitの共同作業

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.ini

HEADは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.ini

recoveredは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 / シェル

1
git log --oneline --decorate cat settings.ini
c7ba33e (HEAD -> main, tag: saved) Set timeout to 30
8939a78 Set timeout to 20
feb47f5 Initial files
timeout=30
2
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
3
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 --short
MM settings.ini
?? notes.txt
4
git reset --soft HEAD^ git show HEAD:settings.ini git show :settings.ini cat settings.ini
timeout=20
timeout=40
timeout=50
5
git reset --mixed HEAD git show HEAD:settings.ini git show :settings.ini cat settings.ini git status --short
Unstaged changes after reset:
M	settings.ini
timeout=20
timeout=20
timeout=50
 M settings.ini
?? notes.txt
6
git reset --hard HEAD git show HEAD:settings.ini git show :settings.ini cat settings.ini git status --short
HEAD is now at 8939a78 Set timeout to 20
timeout=20
timeout=20
timeout=20
?? notes.txt
7
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"
8
git branch recovered saved git rev-parse --short recovered git symbolic-ref HEAD cat settings.ini
c7ba33e
refs/heads/reset-case
timeout=20
9
git show main:settings.ini git show reset-case:settings.ini git rev-list --count main git rev-list --count reset-case
timeout=20
timeout=20
4
2

演習完了