Git入門:バージョン管理のきほん
困ったときの逃げ道(よくある事故と復旧)
この回でやること
間違えて commit した、push してしまった、ブランチを消した。よくある事故を症状から引ける逆引き表にまとめ、落ち着いて戻す手順を身につけましょう。
- 読む 約 8 分
このコースの最後は、事故からの復旧です。一度でも commit していれば、失われるものはほとんどありません。 ブランチを消しても reset で巻き戻しても、コミットはリポジトリに残っていて見えなくなっているだけです。Git が消すのは、コミットを指す名前です。
戻せないのは、一度も commit していない編集だけです。危ないと思ったら、まず commit する。以下、症状ごとに見ます。
main のまま commit してしまった
ブランチを切り忘れて main でコミットした。まだ push していなければ、その場でブランチを作れば片付きます。switch -c はいまいるコミットから新しいブランチを作って移動するので、コミットはそのまま新ブランチに属します。
ターミナル
$ git switch -c feature/login-form
$ git log --oneline -2
$ git switch main
$ git status
$ git reset --hard origin/main最後の行で main をリモートと同じ位置へ戻します。reset --hard は作業ツリーごと消す操作なので、順番が大事です。 git log で自分のコミットが feature/login-form に付いていること、git status で main に未コミットの編集が無いことを見てから打ってください。
push した後で、その commit を消したくなった
ここが分かれ目です。push したコミットに reset は使いません。 他の人の履歴と食い違い、強制 push が必要になります。代わりに revert を使います。
ターミナル
$ git revert a1b2c3d指定したコミットの変更を打ち消す新しいコミットを積む操作です。履歴は書き換わらず後ろに 1 つ足されるので、他の人の手元とも矛盾しません。エディタが開いたら保存して閉じ、普通に push します。
「まだ誰も pull していないはずだから reset でいい」は避けます。確認が取れないなら revert です。
ブランチを消した、pull したら見覚えのない状態になった
消えたように見えるものは、たいてい名前が外れただけです。git reflog は HEAD がどこを指していたかの移動記録なので、そこから拾い直します。
ターミナル
$ git reflog
a1b2c3d HEAD@{0}: checkout: moving to main
9f8e7d6 HEAD@{1}: commit: バリデーションを追加左のハッシュが、その時点でのコミットです。消したブランチの最後のコミットも残っています。拾う前に git show 9f8e7d6 で中身を開き、探しているものかを確かめてください。 確かめたら、そこからブランチを作り直します。
ターミナル
$ git switch -c feature/login-form 9f8e7d6ブランチを作り直す形なので、いまの状態は壊れません。pull で変になった場合も同じで、pull 前の位置を reflog から探し、git show で確かめて戻します。
そもそも、いまどうなっているのか分からない
やってはいけないのは、思い出せないコマンドを次々に試すことです。焦るほど取り返しがつかなくなります。まず状態を見る 3 つを打ってください。
ターミナル
$ git status
$ git log --oneline -10
$ git reflog -20git status は、どのブランチにいるか、何が add されているか、マージの途中かを教えてくれます。マージ中なら次に何をすればいいかまで書いてあります。git log で履歴の並びを、git reflog で自分が何をしてきたかを確かめれば、どの症状かが分かります。この 3 つは、何がどこにあるのかを覗く窓です。
- commit していない編集だけが Git の保護の外にある。危ないと思ったらまず commit する
- push 前なら
reset、push 後ならrevert。この分岐だけは間違えない reset --hardの前はgit logとgit status、reflog から拾う前はgit showで対象を確かめる