先に要点
git checkoutは枝を移る操作と、ファイルを元に戻す操作を1つのコマンドで兼ねていました。この2つは取り消せるかどうかが正反対なので、同じ名前で呼ぶと事故が起きます。- いまは分かれています。枝を移る・作るのが
git switch、ファイルの内容を戻すのがgit restoreです。git checkoutも従来どおり両方できます。 git restoreは戻せません。手元で確かめたところ、コミットしていない変更は実行した瞬間に消え、git fsckでも回収先が出ませんでした。履歴に入っていないものは、Git のどこにも残っていません。- 使い分けは1文で決まります。移動したいなら
switch、捨てたいならrestore。捨てる方だけ、実行前に一呼吸おきます。
git checkout で枝も移れてファイルも戻せるのに、なぜ2つのコマンドが増えたのか。理由は、この2つの操作が失敗したときの結末がまったく違うからです。
この記事では、それぞれが公式にどう定義されているかを確認し、戻せない側で何が起きるのかを手元で再現した結果と、迷わないための判断の順番を整理します。
2つの操作は性質が違う
同じコマンドで呼んでいた2つを並べます。
| やること | 失敗したときの結末 |
|---|---|
| 枝を移る | 移り直せます。元の枝の名前を指定すれば戻れます |
| ファイルを元に戻す | 戻せません。書いていた内容がコミットされていなければ、どこにも残っていません |
片方は移動、もう片方は破棄です。操作の重さが違うものを1つの名前で呼ぶと、手が滑ったときの被害に差が出ます。
公式の定義
git restore のドキュメントは、動作をこう説明しています。作業ツリーの指定したパスを、復元元の内容で置き換える。そして追跡されているファイルが復元元に存在しない場合は、元に合わせるために削除されるとも書かれています。
「置き換える」「削除される」という言葉が使われている点が重要です。いま手元にある内容をどこかへ保存する動作は含まれていません。
既定の復元元はインデックスで、--staged を付けた場合は HEAD です。--source で別のコミットから戻すこともできます。
手元で再現する
どれくらい戻せないのかを確かめます。使い捨てのリポジトリで完結する手順です。
git init -q
echo "1行目" > memo.txt
git add memo.txt
git commit -q -m "初回"
echo "書きかけの2行目" >> memo.txt
cat memo.txt # 2行ある
git restore memo.txt
cat memo.txt # 1行に戻っている
git fsck --lost-found # 回収先が出るか
結果です。
| 時点 | memo.txt の中身 |
|---|---|
restore の前 |
1行目 / 書きかけの2行目 |
restore の後 |
1行目だけ |
git fsck --lost-found |
回収先の出力なし |
「書きかけの2行目」は Git のどこにも残っていません。コミットしていない内容はオブジェクトとして保存されていないので、失われた物の置き場にも現れません。
ここが git reset --hard との違いでもあります。コミット済みのものを巻き戻した場合は参照ログから戻せる余地がありますが、一度もコミットしていない編集には戻る先がありません。
使い分け
迷ったときは、この順で考えます。
- いま書いているものを残したいか。残したいなら、まず
git stashかgit addで退避します - 枝を移りたいだけか。それなら
git switchです。新しく作って移るならgit switch -c - ファイルを捨てたいのか。それが目的なら
git restoreです
1番を飛ばさないことが唯一の予防です。2番と3番は取り違えても switch 側なら戻れますが、逆はありません。
checkout はどうすればよいか
使い続けても問題ありません。従来の動作はそのままで、git checkout で枝を移ることもファイルを戻すこともできます。既存の手順書やスクリプトを書き換える必要はありません。
一方で、これから覚えるなら分かれている方を選ぶ意味があります。コマンド名を見た時点で、それが移動なのか破棄なのか分かるからです。Git の公式ドキュメントも、巻き戻し系の3つのコマンドの違いについて別に解説を用意しています。
チームで決めるなら、破棄する操作だけ restore に寄せるのが現実的です。全部を切り替えるより摩擦が少なく、危ない操作が名前で分かるという利点だけ取れます。
git switch と git restore に関するよくある質問
Q. git switch に checkout でできたことが全部ありますか?
枝の移動と作成という範囲では足ります。ファイルの復元は switch には含まれません。それが分割の趣旨なので、ファイルを戻したいときは restore を使います。
Q. 誤って git restore を実行しました。戻せますか?
コミットもステージもしていなければ、Git からは戻せません。エディタの取り消し履歴や、エディタが持つローカル履歴の機能が残っていれば、そこから拾えることがあります。Git に期待するのは難しい状況です。
Q. git restore と git reset はどう違いますか?
restore は作業ツリーやインデックスの中身を対象にし、reset は枝が指している位置も動かせます。公式ドキュメントが3つのコマンドの違いを解説する節を別に持っているので、迷ったらそこを見るのが確実です。
Q. 事故を防ぐ運用はありますか?
作業の切れ目ごとにコミットしておくのがいちばん効きます。コミットしてあれば、巻き戻しても参照ログから戻せます。細かいコミットは後でまとめられるので、残しておく方が得です。
まとめ
git checkout は移動と破棄という、取り消せるかどうかが正反対の操作を兼ねていました。いまは git switch が移動、git restore が破棄です。
再現して確かめたとおり、コミットしていない編集は restore の瞬間に消え、Git のどこにも残りません。だから覚えることは1つです。捨てる前に、残したいものを退避する。