2013-11-12

Jenkinsの開発者、間違えて一ヶ月前のローカルレポジトリをgit push --forceしてしまう

Jenkin developers accidentally do "git push --force" to over 150 repos on github | Hacker News

Jenkinsの開発者、Luca Milanesioによって、Jenkinsの多くのgitレポジトリに対してpushが行われた。不思議なことに、pushをしたというのに変更点はほとんどみられない。一体ルカは何をやったのだ。

Dominik Bartholdi

やあみんな、とくにルカ。

昨日、GitHub上のJenkinsの多くのレポジトリ(50以上)に、なにか変なことが起こった。

どうやら、Luca Mmilanesioが、何の変更もないのに、たくさんのたくさんのレポジトリにpushしたらしいのだ。少なくとも、俺には変更がみえない。

https://github.com/organizations/jenkinsciから、昨日をみると、多くのレポジトリに多くのpushが行われている。

俺はなにか勘違いをしているのかな?

どうも俺が思うに、これは誰か、GitとGitHubの仕組みを理解していない奴が、間違えてすべてのレポジトリにpushしたんじゃないのか。なにか壊れてないか確認したほうがいいのでは?

敬具など Domi

strange pushes on GitHub - Google Groups

Luca Milanesioは、どうやら一ヶ月ぐらい前のローカルレポジトリから、GitHubのリモートレポジトリに対して、git push --forceしてしまったらしい。

Luca Milanesio

やあ、みんな

昨晩、以下のJenkins-CIプラグインに、間違えて"forced push"を引き起こしてしまった。

謝罪

俺がforced pushできる権限を持ってるとは思わなかったんだ。本当にすまない。

この操作によって、すべてのブランチが約一ヶ月前に巻き戻ってしまった。歴史は消えずにGitHubのサーバーに残っているが、すでにデタッチされたブランチにある。

解決法

GitHubに頼んで、これらのレポジトリに対して"reflog"してもらった結果を送ってもらい、俺のforced pushの前の状態にまでブランチを戻す。

あるいは、各レポジトリの所有者が、"forced push"してブランチを正しい位置まで戻す。

(これをやるなら、二重にやるのを防ぐため、メーリング・リストに書いてからやってくれ)

strange pushes on GitHub - Google Groups

通常、gitはローカルがリモートの子孫でない限り、pushを拒否する。つまり、ローカルがリモートからpullしてコミットするまでの間に、リモートに変更が生じた場合は、pushを拒否する。通常は、ローカルがリモートから一度pullして、あるいは必要に応じて手動でマージしてから、pushする。

git push --forceは、このpushの拒否を無効にし、リモートを強制的にローカルに合わせる。つまり、リモートレポジトリはローカルレポジトリと同じ状態になるのであって、リモートに対するローカルに落とした以降の別のコミットはすべてなかったことになり、歴史が改変される。

gitは、間違えてgit push --forceしてしまった場合でも、普通は簡単に元に戻すことができる。なぜならば、歴史は改変されたものの、消えてはいないからだ。reflogでpush --forceの直前のハッシュ値を確認して、branch -fで、そのハッシュ値の状態に戻せばいい。

問題は、これはgitレポジトリを直接に操作できる場合である。GitHubのリモートレポジトリに対して、ユーザーはその操作ができない。GitHubのサポートにreflogを実行してもらうよう頼むなどと言っているのは、そのためだ。

Luca Milanesio

悲惨だな(´・ω・`)・・・ force pushは危険だ。特に、gitサーバーをコントロールできない場合は。

普通、force pushを直すのは簡単なんだけど:

  1. git reflogして、forced pushの前のSHA-1を確認
  2. git branch -f <name> <sha-1>

ただし、サーバーにあるgitレポジトリをコントロールできない場合、force pushを禁止する必要がある。あるいはみんなGHエンタープライズを買うか。

GitHubの運営が1.と2.をしてくれればいいんだが(^_^;)

Luca.

strange pushes on GitHub - Google Groups

幸い、GitHubの運営は、push --forceする直前のレポジトリのハッシュ値のリストを抽出して送ってくれたらしい。また、push --force直前の状態をrecoveryというブランチ名で作ってくれたらしい。

まあ、何しろJenkinsという著名なソフトウェアのレポジトリでもあるし、GitHubの対応は早かったようだ。

議論は、やはりコントロールできないリモートのサーバー上のgitレポジトリに依存する場合に、全員に全レポジトリのpush --forceの権限が与えられるべきではないという方向に進んでいるようだ。

8 comments:

Anonymous said...

初期状態でpushの履歴を見ることができるならそれが一番良いのでしょう。
ただ、githubの場合、WebHookの機能でpush直前のHEADとpush直後のHEADのコミットIDを両方とも送ってくれているので、それを記録するようなフックを書いてこの手の災害に備えています。

Anonymous said...

「リ」ポジトリ
だよー

江添亮 said...

GitHubにreflog結果をダウンロードできる機能を追加するか、あるいはリモートリポジトリ側でreflogを実行できる何らかの方法が望まれるところ。

歴史改変は書くも怖い。

そういえば\ri-ˈpä-zə-ˌtȯr-ē\ですね。
ただ、実際の発音を聞いても、どうもレポジトリと聞こえてしまう。
次からリポジトリにします。

江添亮 said...

やっぱりレポジトリにしておこう。

Anonymous said...

発音記号 ɪ は、イとエの中間の音ですから、
どっちでも良いでしょうね。
economyもエコノミーですし。

Anonymous said...

レポでもリポでもどっちでもおかしくはないと思う

プログラマとかサーバとかメンバとかみたいに、伸ばし棒を省略する方がはるかにおかしいし、気持ち悪い

まあオタクってそういうもんかもしれないけどね。。。

Anonymous said...

今でも語尾の長音を省略する人は、単語間のハイフンと長音の見分けが付かないというJISが変わったことを知らない老害なので全無視で良いと思いますよ。

Anonymous said...

そうか、レポジトリーに直さないとな。