Git reset/rebase/revert ======== {{tag: git}} いろいろ元に戻したいときもある -------- {{TOC 3-}} ### git で戻す系の操作 ### 編集をやり直したいとか commit をやり直したいとかいろいろとにかくやり直したい場面というのはやってくる。 push 前なら、git は考えうるほとんどのやり直しを実現してくれる。 ### checkout ### 編集した内容を取り消す。ただし、add されたものまでは取り消さない。 $ git checkout -- path/to/file HEAD 時点に戻す。 $ git checkout HEAD path/to/file git-checkout は、branch の切り替えだけでなく、ファイルパスを引数にすることでファイルの編集をある地点に戻す(たぶん checkout というコマンド名からすれば直感的)という挙動をする。 ### reset ### add したのを取り消す。 $ git reset path/to/file ワークツリー全体の add したのを取り消す。 $ git reset HEAD 1つ前のコミットを取り消す。ただし、手元の編集分はそのまま。 $ git reset HEAD^ 1つ前のコミットを取り消す。そして手元の編集分もなかったことにする(--hard)。 $ git reset --hard HEAD^ 取り消したコミットは、「ORIG_HEAD」で参照できる。 以下のようにすると、取り消したコミットとの差分を参照できる。 $ git diff ORIG_HEAD ### rebase ### rebase は、現在の差分のはじまり(分岐点)を変更する。 $ git checkout master $ git pull $ git co -b sample-branch .-- sample-branch / D---E-- master その後、master/sample-branch 両ブランチともに編集が進む。 [こんな状況とする] A---B---C sample-branch / D---E---F---G master 現在は master は G までコミットが進んでいる $ git rebase master [こうなる] A'--B'--C' sample-branch / D---E---F---G master sample-branch での差分は、G から分岐したものになる。 カレントのブランチの派生元を操作するのが rebase master から乖離した手元のブランチに、差分を取り込む場合に、 $ git rebase master すると、master の差分を入れた後に、自分がブランチに入れていた差分が入る。 * rebase は他にもいろいろと機能がある。 ### revert ### revert は指定するコミットまでtreeを差し戻す。 reset との違いは、コミットを取り消して差し戻したという作業が、履歴に残る。 $ git revert ### remote のコミットをやり直す remote を操作するのは危なっかしいので推奨しないが、以下のようにすると、remote のコミットを強制的に消せる。 $ git push -f origin HEAD^:master