先日、あるプロジェクトのブランチを整理しようという話になり、 git reset --hard をすることになりました。
このコマンドについて私は「以前のコミットを無かったことにする」くらいの認識でいました。
さらに、お恥ずかしいことにhardをforce的な意味だと思っていました。(強制的にリセットするよ!みたいな)
今回は備忘録として、ブランチの本質的な概念とreset オプションの違いについてまとめました。
ブランチとは
ブランチ
そもそもブランチについてどういうものかを問われた際に明確に答えられますか?
当たり前の存在すぎて説明できない方も多いのではないでしょうか。
私は分かっているつもりになっていました。
「ブランチを切る」という表現をよく使うのでコミット履歴のつながりそのものを指すと勘違いされがちですが、実際は「コミットを指し示している可動式のポインタ」です。
「ブランチを切る」というのは、枝を切断するという意味ではなく「新しくブランチを作る」という意味です。
ブランチはコミットの参照に過ぎないということです。
HEAD
ではHEADはなんでしょうか。個人的に似ていると感じているので挙げてみました。
HEADは「今自分がチェックアウトしている(作業している)ブランチ」を指し示すポインタです。
- ブランチ:コミットを指す
- HEAD:ブランチを差す
(ブランチを切るという表現は間違い...?)
git reset --soft
では本題です。まずは git reset --soft から。
git reset --soft HEAD~
このコマンドを実行すると、「HEADの場所」だけが移動します。
-
何が変わる?
直近のコミット履歴が消え、HEADが以前のコミットに移動します。 -
データはどうなる?
ステージングの内容や作業ディレクトリの内容は保持されます。
「コミットメッセージを書き直したい」「複数のコミットを一つにまとめたい」という時に便利です。
git reset --hard
git reset --hard HEAD~
そして今回私が勘違いしていた` git reset --hard `です。 これはHEADを移動するだけではなく、「ステージングの内容」と「作業ディレクトリ」の両方を指定したコミットの状態に強制的に戻します。
-
何が変わる?
コミット履歴、作業ディレクトリ(書きかけのコード)全てが指定した時点に戻ります。 -
注意点
まだコミットしていない変更はすべて消去されます。 私が「force(強制的)」だと思っていた部分はあながち間違いではありませんが、その対象が「履歴」だけでなく「今書いているコード」も含めて「すべてをなかったことにする」という破壊的な意味での強さだったのです。
まとめ
| オプション | HEADの移動 | ステージング | 作業ディレクトリ (コード) | 主な用途 |
|---|---|---|---|---|
--soft |
✅移動する | 保持される | 保持される | コミットメッセージの修正、コミットのまとめ |
--mixed |
✅移動する | ❌リセット | 保持される | 直前の git add を取り消したい時 |
--hard |
✅移動する | ❌リセット | ❌リセット | 作業を完全に破棄して過去の状態に戻したい時 |
git reset --hard は強力ですが、未コミットの作業が消えてしまうと復旧が非常に困難です。
変更を一時的に退避させたいなら git stash
コミットをやり直したいだけなら git reset --soft
このように、目的(どこまでをリセットしたいのか)に合わせて使い分けられるように明確な理解が必要だと感じました。

