「○日のソフトだったら動いていたのに。。。」ということはよくある。
そんなときgitリポジトリではどうやって環境を再現するべきなのだろう。
結論を先に書いておくと、「きちんと運用をしておかないと機械的に厳密に再現することはできない」
#良い方法があったら教えてください。
真っ先に思いつくのはgit log -1 --until=2013-01-23
などでその日付以前の最後のコミットを抽出し、checkoutするという方法。
だがこの方法には落とし穴がある。指定した日付以降にmergeした修正(当時まだ導入していない修正)を、checkoutしてしまう可能性があるのだ。
例えば下記の操作をした場合、2013/01/23リリースのソフトといえばcommit1までをcheckoutしたいが、実際にはcommit2までをcheckoutしてしまう。
[2013-01-22]
git checkout release-branch
git commit -m "commit1"
[2013-01-23]
git checkout topic-branch
git commit -m "commit2"
[2013-01-24]
git checkout release-branch
git merge topic-branch
(2013-01-23リリースのソフトで不具合発覚)
git checkout `git log -1 --until="2013-01-23" --format=%H`
いやらしいのはgit log
を見る限りちゃんと日付で取り出せているように見えるので、知らず知らずのうちにぜんぜん違うソフトで作業してしまう可能性があることだ。
ではどう運用すればいいのだろうか。いくつか思いつく運用を列挙してみる。まぁ1か2が無難。
-
リリースブランチにmerge後、毎回タグをうつ
これが一番オーソドックスかつ確実。運用ルールを理解していない人が先走ってmergeしてしまった場合も、後追いでタグを打つこともできる。 -
リリースブランチにmerge後、毎回リリースブランチにコミットする
バージョンやリリースノートをリポジトリ内のファイルで管理している場合、この方法が自然。checkoutするときはバージョンファイルに対してgit log -1 --until
すればOK。欠点はファイル構成が変わってしまった場合少しトレースしにくくなること。なのでコミットログのフォーマットを決めておくとベター。 -
リリースブランチにmergeするときに、リリースブランチがfirst parentになるように気をつける
この運用がうまくいけば、git log -1 --first-parent --until
で取り出せる。ただこれは共同開発するときに周知するのが難しいかな。。。見た目にもそういう運用をしていることが見えにくいので無意識に壊されてしまう可能性が高そう。
参考:git log --first-parentのすゝめ -
mergeしない
常にリリースできる単位でしかコミットせず、他の誰かがコミットしてたらコミットやりなおし。。。できると思わないし、やりたくもないけど。てゆーかこんな神がかり的な運用ができるならgitいらないか。