8月22日のオンラインLT会 で発表した git reset
について。LTでは時間の関係上削除した部分もあるので、そこも含めて書いてみる。
git reset
git reset
は、HEAD
を戻すコマンド。コミットやインデックス、ワークツリーのデータを消すことができる(復元が不可能というわけではない)。
git reset のオプション
オプション | 動作 |
---|---|
--soft | HEAD だけ戻す |
[--mixed] | HEAD とインデックスを戻す |
--hard | HEAD とインデックスとワークツリーを戻す |
(--mixed は省略可)
3つのオプションがあるが、上の表のとおりそれほど複雑なわけではない。git reset
を検索すると、図を交えたわかりやすい説明がいくつも出てきて、読めば理解できる。にもかかわらず、実際動かしてみるとなんか思った動きと違う…。
インデックス(ステージングエリア)についての誤解が原因
インデックスについて誤解していたことに気づいたのは、LTの前々日だった。
LTをやると決めてから、スライド用の図を作ったり説明を考えたりしていた。そのときもまたgit reset
についてのいろいろなプログ記事やドキュメントを読んで、「理解できているつもり」で準備を進めていた。
今まで何度も理解したつもりになって理解できてなかったのに、今自分が作っている図だと、誤解ポイントがない。自分の誤解ポイントを共有したいのに、どこをどう勘違いしていたのか自分でもわからないという状態だった。
インデックスって何?
特にインデックスに焦点を当てるつもりはなかったが、流れ上全く説明しないのも不親切な感じだったので、簡単な説明を書くことにした。
最初に書いた説明はこんな感じ。
「インデックス:コミットするものを一時的に置く場所」
インデックスについて深く考えたことがなかったので、適当に書いたらそうなった。しかし、LTする以上正しいことを伝えなければいけないので、裏付けのためにインデックスについて調べることとなった。
わかったこと。インデックスについての情報は少ない。というかたどり着くのが難しい。
コミットする前に git add
でインデックスに登録しないといけないよ、という以上の情報があまり出てこない。
もちろんドキュメントは見た。ドキュメントの説明は、“次のコミット候補のスナップショット”。スナップショット??スナップショットってこのスナップショット?
その時点の状態を、そのまま丸ごと保存したもの
スナップショット (snapshot)とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
なんか自分のイメージと違う。正直、インデックスについてあまり考えたことがなかったが、なんとなく、自分のイメージはこんな感じだったんだと思う。インデックスには、前のコミットとの差分だけが保存されて、コミットすると、そのデータがコミットに移っていくイメージ。
こう考えていたせいで、git reset
の動きが理解できなかったのだ。
インデックスとは
インデックスは、次のコミット候補のスナップショット。「差分」ではなく、次のコミットの丸ごとのコピーだ。
git ls-files
というコマンドで、インデックスのファイル一覧を見ることができる。前にadd
したファイルもちゃんとあることが確認できる。LTのスライドを見てほしい。
インデックスについては、こちらの記事がとても参考になった。
ということで、インデックスについて理解できたら、git reset
はすんなり理解できた。
git reset の取り消し
reset
したことを取り消すこともできる。
git reset --hard ORIG_HEAD
で、リセット前の HEAD
に戻せる。
git reset の例
図がわかりやすいという声をたくさんいただいたので、時間の関係で省いた HEAD~2 の画像もはっておく。
git reset --soft HEAD~2
git reset HEAD~2(オプション省略)
git reset --hard HEAD~2
おまけ
『パーフェクト Ruby on Rails』や『ゼロからわかるRuby超入門』の著者でもある igaiga さんからのコメント!!とってもうれしい!
masuyamaさんの資料でgit reset —soft完全に理解した。運営もおつかれさまでした。 / 1件のコメント https://t.co/EDSR2Wkn4c “「初めてのLT会 Vol.4」開催 - No Solution for Life” https://t.co/RoTAkuWpLu
— igaiga (@igaiga555) August 23, 2020