origin
がhttps://github.com/[username]/[reponame]
というgithub上で管理しているリモートリポジトリだとする。
ここで誰かが間違えて、必要な変更を失ってしまうようなgit push -f origin master
をやってしまった場合の話。
force-pushed branch master of [username]/[reponame] from 1e6753 to 8cec0c
8cec0c
ではなく1e6753
の状態に戻したいが、1e6753
は誰のローカルにも存在しなく、github上でもタグや名前が付けられてないのでfetchしてくることが出来ないとする。
https://github.com/[username]/[reponame]/commit/1e6753
にアクセスすれば、1e6753
がどんなコミットであったか分かる。
ここでは、1e6753
が255番目のMerge Pull Requestだと分かったとする。
直接、masterにpushするというような運用をしていななければ、たいてい最新のmasterは何らかのMerge Pull Request後であると思う。
$ git ls-remote origin
でremote originにある全てのreferenceがわかり、Github上にはref/pull/番号/merge
とref/pull/番号/head
が全てのpull requestに対してあるというのがわかる。
これらは全てローカルにfetchしてくることが出来るので、あとは
$ git fetch origin refs/pull/255/merge
From github.com:[username]/[reponame]
* branch refs/pull/255/merge -> FETCH_HEAD
$ git checkout FEACH_HEAD
$ git checkout -b old_master
$ git log (確認)
$ git push -f origin old_master:master
とやれば1e6753
と同じ内容にmasterが戻る。
実例で説明できない分ちょっとわかりにくくなってしまったが、これは実際に起った問題で、意外とWeb上に情報がない問題だったりする。実際にこうやることで直せたので誰かの役に立つことを期待。push -f
はたまに必要だったりするけど怖い・・・。