Git インデックスと reset --soft / (--mixed) / --hard を理解する

8月22日のオンラインLT会 で発表した git reset について。LTでは時間の関係上削除した部分もあるので、そこも含めて書いてみる。

speakerdeck.com

git reset

git resetは、HEADを戻すコマンド。コミットやインデックス、ワークツリーのデータを消すことができる(復元が不可能というわけではない)。

Git - リセットコマンド詳説

git reset のオプション

オプション 動作
--soft HEAD だけ戻す
[--mixed] HEAD とインデックスを戻す
--hard HEAD とインデックスとワークツリーを戻す

(--mixed は省略可)

3つのオプションがあるが、上の表のとおりそれほど複雑なわけではない。git resetを検索すると、図を交えたわかりやすい説明がいくつも出てきて、読めば理解できる。にもかかわらず、実際動かしてみるとなんか思った動きと違う…。

インデックス(ステージングエリア)についての誤解が原因

インデックスについて誤解していたことに気づいたのは、LTの前々日だった。

LTをやると決めてから、スライド用の図を作ったり説明を考えたりしていた。そのときもまたgit resetについてのいろいろなプログ記事やドキュメントを読んで、「理解できているつもり」で準備を進めていた。

今まで何度も理解したつもりになって理解できてなかったのに、今自分が作っている図だと、誤解ポイントがない。自分の誤解ポイントを共有したいのに、どこをどう勘違いしていたのか自分でもわからないという状態だった。

インデックスって何?

特にインデックスに焦点を当てるつもりはなかったが、流れ上全く説明しないのも不親切な感じだったので、簡単な説明を書くことにした。

最初に書いた説明はこんな感じ。

「インデックス:コミットするものを一時的に置く場所」

インデックスについて深く考えたことがなかったので、適当に書いたらそうなった。しかし、LTする以上正しいことを伝えなければいけないので、裏付けのためにインデックスについて調べることとなった。

わかったこと。インデックスについての情報は少ない。というかたどり着くのが難しい。

コミットする前に git add でインデックスに登録しないといけないよ、という以上の情報があまり出てこない。

もちろんドキュメントは見た。ドキュメントの説明は、“次のコミット候補のスナップショット”。スナップショット??スナップショットってこのスナップショット?

その時点の状態を、そのまま丸ごと保存したもの
スナップショット (snapshot)とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典

なんか自分のイメージと違う。正直、インデックスについてあまり考えたことがなかったが、なんとなく、自分のイメージはこんな感じだったんだと思う。インデックスには、前のコミットとの差分だけが保存されて、コミットすると、そのデータがコミットに移っていくイメージ。

f:id:masuyama13:20200823222104p:plain

こう考えていたせいで、git resetの動きが理解できなかったのだ。

インデックスとは

インデックスは、次のコミット候補のスナップショット。「差分」ではなく、次のコミットの丸ごとのコピーだ。

git ls-files というコマンドで、インデックスのファイル一覧を見ることができる。前にaddしたファイルもちゃんとあることが確認できる。LTのスライドを見てほしい。

インデックスについては、こちらの記事がとても参考になった。

engineering.mercari.com

ということで、インデックスについて理解できたら、git reset はすんなり理解できた。

git reset の取り消し

resetしたことを取り消すこともできる。

git reset --hard ORIG_HEAD で、リセット前の HEAD に戻せる。

git reset の例

f:id:masuyama13:20210215170214g:plain

図がわかりやすいという声をたくさんいただいたので、時間の関係で省いた HEAD~2 の画像もはっておく。

git reset --soft HEAD~2

f:id:masuyama13:20200823225720p:plain

git reset HEAD~2(オプション省略)

f:id:masuyama13:20200823225802p:plain

git reset --hard HEAD~2

f:id:masuyama13:20200823225825p:plain

おまけ

『パーフェクト Ruby on Rails』や『ゼロからわかるRuby超入門』の著者でもある igaiga さんからのコメント!!とってもうれしい!