これは何
新人プログラマ応援イベントの参加記事です。
gitにはreflogというコマンドがあります。このコマンドを学んでおくとやらかしちゃった時も大体なんとかなるので記事にします。
git reflogってなに?
git reflogとは、Gitで操作履歴を見ることができるコマンドです。
例えば
- 
branch1にチェックアウト
- 
branch1でbranch1.txtを作成し、コミットを作る
- 
masterにチェックアウト
をすると、以下のようなreflogになります。
$ git reflog
4a4125a (HEAD -> master) HEAD@{0}: checkout: moving from branch1 to master
826a9dc (branch1) HEAD@{1}: commit: Create branch1.txt
4a4125a (HEAD -> master) HEAD@{2}: checkout: moving from master to branch1
このコマンド自体はそれだけなのですが、他のコマンドで一緒に表示される作業番号(HEAD@{0})はHEADなどと同じ作業ポインタとしてさまざまなコマンドに指定できます。
その特性を生かしたやらかし解決法を紹介していきます。
やらかしをなんとかする
@ryozi_tn さんに、より詳しい説明や、注意点、参考資料についてコメントいただいたので、本文と合わせて読んでみてください
https://qiita.com/getty104/items/cfd98f5f0ea89ef07bf0#comment-8585c38b84ae67c281f0
間違えてgit reset --hardで必要な変更も消しちゃった
上の例で、例えばbranch1でgit reset --hard HEAD~を実行し、間違えてコミットした変更を削除してしまったとします。しかし変更した内容は必要なものだったので、このままだと全く同じ作業をまたやらないといけなくなります。最悪です。
しかしこんな場合もgit reflogを使えばなんとかなります。
まずはgit reflogで作業ログを出します。
$ git reflog
4a4125a (HEAD -> branch1, master) HEAD@{0}: reset: moving to HEAD~
826a9dc HEAD@{1}: checkout: moving from master to branch1
このgit reflogを見ると、HEAD@{0}という作業番号で誤ったgit reset --hard HEAD~を行っていることがわかります。この作業を取り消し、コミットを復活させたいです。
git reflogの作業番号、実はそのままgit resetの引数に指定することで、その作業を行っていた時の状態に戻せます。
今回はHEAD@{1}に戻りたいので、git reset --hard HEAD@{1}を実行します。
実行を行うことで、コミットも元通り、変更内容も復活します。
間違えて必要なブランチ消しちゃった
続いて、間違えてmasterにいる状態でbranch1を削除してしまった場合を考えます。
削除後のgit reflogの結果は以下の通りです。
$ git reflog                                                                                                                                                                                         
4a4125a (HEAD -> master) HEAD@{0}: checkout: moving from branch1 to master
9d0bac1 (branch1) HEAD@{1}: commit: Create branch1.txt
4a4125a (HEAD -> master) HEAD@{2}: checkout: moving from master to branch1
間違って削除をしてしまったブランチに戻りたいです。
git reflogを見ると、HEAD@{1}でbranch1でのコミットを作っていたようです。
そこで、git branch branch1 HEAD@{1}を実行します。そうすることで、HEAD@{1}までの作業履歴をbranch1としてコピーすることができるので、ブランチが復活します。
git commit --amendでコミットに不要な変更混ぜちゃった
branch1でbranch1-2.txtというファイルを作成し、新たにコミットを作るはずが誤ってgit commit --amendを用いて一つ前のコミットに変更を混ぜてしまったとします。
git reflogの結果は以下の通りです。
a04365e (HEAD -> branch1) HEAD@{0}: commit (amend): Create branch1.txt
9d0bac1 HEAD@{1}: checkout: moving from master to branch1
一旦コミットを取り消し、再度コミットを作り直したいです。
HEAD@{1}に作業だけ戻り、ファイルの変更は残しておければそのままコミットを作り直せそうです。
そこでgit reset --soft HEAD@{1}を実行し、作業だけ巻き戻します。
これでファイルの変更は残しておいたまま、作業だけ取り消せたのでコミットを作り直すことができます。
まとめ
git reflog自体はただ履歴を確認するためのシンプルなコマンドですが、それを応用することでいろんなやらかしを取り消すことができます。
ここで紹介したやらかし以外でも解決できることはたくさんあるので、もしGitを使って何かやらかしてしまった際はgit reflogを使ってなんとかできないか考えてみてください。

