DMM.comラボエンジニアブログ

DMM.comラボのエンジニアブログです。DMM.comを支える技術について書いています。

DMM insideに引っ越しました。 移転先はこちら -> https://inside.dmm.com/

gitだいじっけん - 闇に飲み込まれたコミットを救出せよ -

あけましておめでとうございます。
DMM.comラボ新卒エンジニアのへれんです。

皆さん年末年始はいかがお過ごしでしたか。
今年1つめのブログは年末に起きた悲劇のお話を書きました。


目次

事件は隣の席で起きていた

$ git branch -a
$ git checkout remotes/origin/feature/develop-xxxx # ここがすべての始まりであった...
$ git add some-files
$ git commit -m "some messages"
$ git push origin

隣の人「コミットが闇に吸い込まれた」
私「!?」

github, git log, tig で見てもコミットはいませんでした

コミットはいずこへ...

追跡ブランチにコミットしていたのが原因でした

$ git checkout remotes/origin/feature/develop-xxxx # remotes/origin/がついてるのが追跡ブランチ

追跡ブランチとは

traking branch
追跡ブランチともいう。
これは何かというと、リモートリポジトリのブランチを追跡するためだけのブランチ。

基本的にこのブランチにコミットとかマージはしちゃダメ。
pushとかpull(正確にはpullじゃなくてfetchのとき)したときに勝手に最新の情報に更新されるようになってるという特殊なブランチ。

追跡ブランチというのはリモートブランチの状態を同期するだけのブランチなので、コミットもマージもすべきではない。
その証拠?に、追跡ブランチをチェックアウトしようとすると、一応チェックアウトはできるものの、detached HEADという「切り離されたHEAD」というものになってしまう。

参考:http://d.hatena.ne.jp/hokaccha/20120404/1333507076

$ git branch
* (HEAD detached at origin/feature/develop-xxxx)
  feature/develop-xxxx
  master

detached(孤立した)ブランチになってしまい、github には認識されない

対処法(本来のブランチにコミットを持ってきたいとき)

  1. ログを漁って HEAD detached at origin/feature/develop-xxxxにコミット(プッシュ)した時のハッシュ値を捜索。
  2. 本来プッシュしたかったブランチ(feature/develop-xxxx)に移動。
  3. git cherry-pick <1で発見したハッシュ値>

コミットはどこにいたのか

detached head には対応するブランチがない。 別のブランチに移ってしまうとどこからも参照されなくなり、そのうち git の garbage collection プロセスで削除されてしまう。
参考:http://transitive.info/article/git/command/checkout/

闇の中にいた模様。

detached状態でもコミットはできるけど、そのコミットを参照するものがいないので別のブランチをチェックアウトするとそのコミットが参照されなくなり見えなくなった模様。

ある程度時間が経つとガベコレに抹殺されてしまうので救出はお早めに。

gitの優しさ

If you want to keep them by creating a new branch, this may be a good timeto do so with:
 git branch new_branch_name 31de5dd
# detached状態のコミットを保持したければブランチを作るがいいわ!という教え

追跡ブランチにコミットしても ↑ のようにブランチ作って救出することもできるよってちゃんと教えてくれます。
(これだとこのブランチを本来のブランチにマージしてコミットログが荒れそうな予感がするので私はcherry-pickのほうが好きですが)




gitさんすごい!