git の push.default の設定値と、ブランチの指定がない push には注意

git で master ブランチを壊すという類まれなる酷い事をやらかしたので、備忘録がてら以下の内容をまとめ。

  • 何をやらかしたのか
  • どうしてそうなったのか
  • どうすれば防げたのか

push.default とか初めて知った・・・ orz

1, 何をやらかしたのか

作業用ブランチでマージ作業をしてたんですが、その際に以下のコマンドで master ブランチをぶっ壊しました。

 $ git push -f

ぶっ壊した際の状況は以下のとおり。

  • local の master ブランチは push 出来ない状態(originと差異がある上にマトモな状態ではない)
  • 現在 checkout されているのは作業用ブランチであり master ではない
  • 作業用ブランチでは rebase を行なっており、push するには -f せざるをえない状態

2, どうしてそうなったのか

git では push 時の動作を決める push.default という設定項目があり、デフォルトでは以下の設定になっています。

matching

そして、これは以下のように振る舞います。

push all branches having the same name in both ends.

・・・・はい、どぼんですね。
詳しくは https://github.com/git/git/blob/master/Documentation/config.txt を参照して下さい。

つまり、現在 checkout してるのがどんなブランチであれ、local と origin の両方に存在していて差分があれば push されちゃうのが現状(1.8)のデフォルト値です。
そして救えない事に今回は -f しちゃったんですよねー。
そういうわけで、マトモな状態ではない master が force で push されるという惨劇をやらかしてしまいました。

3, どうすれば防げたのか

色々ポカミスが重なってやらかしたんですが、やらかした後に色々話したり自分で調べたりして出たのが以下の様な内容ですね。

  • local の master ブランチを壊した状態で放置しない
  • push する際にはブランチを明示する
  • -f せざるを得なくなる rebase を避ける
  • rebase したい場合は fork して別レポジトリにする事で、やらかしても被害を最小限に食い止める
  • push.default を simple にしておく
  • などなど・・・

ちなみにですが、local の master ブランチがぶっ壊れてたのは、マージ作業する際に間違えて作業用ブランチではなく master ブランチで作業したりしちゃったせいです。
後で rollback すればいいか、と思ってそのままにしちゃったのが駄目でしたね。
あと、今回は壊した事にそもそも気づけてないという駄目っぷりも発揮したので、git 力を上げるべく精進することにします。 o...rz