Djangoのブランチ戦略
ブランチ管理パターン
質問
Release 用のブランチが1、トピックブランチ(機能ブランチ)が複数のとき、どういう流れでブランチをマージしていくベストな方法?
前提
仕事のプロジェクトでDjangoを使った社内業務システム向けアプリ
検証リリースが週に3,4回あって、複数の機能やバグ修正が同時に1つの検証環境にリリースされている
本番リリースが週に1,2回あり、検証OKとなった機能やバグ修正がリリースされる
機能やバグ修正はそれぞれトピックブランチで実装されている
戦略1: シンプルイズベスト
ブランチ戦略
master + トピック
master: 本番リリース用
トピック: masterからブランチして、個別の機能やバグ修正を実装
https://jsfiddle.net/shimizukawa/pasw3ecy/14/
https://gyazo.com/4e49a05700c46618c60f2b4f7914f25b
マージ戦略
トピックブランチは、動作確認が終わった、masterにどんどんマージしていく
トピックブランチは、masterが更新されたら、masterを取り込む(マージする)
リリース戦略
masterをある時点でリリースする。
リリース時にリリースタグを作成する
メリットとデメリット
👍シンプルで分かりやすい
動作検証は、トピックブランチで行う。
👍テストで複数の機能同士の影響を考慮しなくてよい。
👎同時に1機能のテストしかできない。複数の機能をまとめて動作検証したり、複数テスターが機能別にテストを分担したりはできない。
👎動作検証のトピックブランチを切り替えるとき、マイグレーションのリセットが必要になる。
👎masterにマージされているブランチが本番リリース済みとは限らない
👎トピックブランチのmasterマージと、本番リリースのタイミングが異なるため、何がリリースされるのか把握する方法が別途必要
戦略2: ChangeLogの導入(+戦略1)
目標: リリース内容が分かるようにしよう
ブランチ戦略
master + トピック
戦略1と同じだが、以下を追加
トピックブランチを作ったら、CHANGELOGファイルにそのトピックブランチでの変更内容を記載する
code:CHANGELOG.rst
=========
CHANGELOG
=========
未リリース
==============
* #2031 <https://github.com/org/proj/issues/2031>_ 出荷日をPDFに印字する
(以下、リリース済みのCHANGELOGが続く)
マージ戦略
戦略1と同じだが、以下を追加
masterからトピックブランチへのマージでCHANGELOGファイルがconflictしたら、修正を行う
TODO: Gitgraph.jsを使ってブランチイメージを用意する
リリース戦略
戦略1と同じだが、以下を追加
リリース時に、CHANGELOGファイルの「未リリース」を「2019/10/01 Release」に置き換える
上記のCHANGELOG更新後にリリースタグを作成する
リリース後に、CHANGELOGファイルに「未リリース」セクションを用意する
メリットとデメリット
👍CHANGELOGを書くことで、masterブランチがいまどんな状態なのか、見れば分かるようになる。
👍トピックブランチ実装中に気づいた重要情報(リリース時に行う手順など)をCHANGELOG書いておける。
👎マージするときにconflictが起きる確率が上がる。誰も触らないようなところのコード修正のトピックブランチでも、CHANGELOGはconflictする可能性が高い。
アンチパターン: CHANGELOGはマージ後に書こう
ブランチの作業目的がブレやすくなる(OSS等で外部のコントリビューターからのPRの場合、目的がブレやすいものなので、一概にアンチパターンとは言えない)。
👎トピックブランチ実装中に気づいた重要情報(リリース時に行う手順など)をCHANGELOG書いておけなくなる。
戦略3: 検証用ブランチの導入(+戦略2)
目標: 複数の機能を同時に検証できるようにしよう
ブランチ戦略
master + トピック + acceptance
acceptance 検証用。baseはmasterで複数のトピックブランチがマージされている。
マージ戦略
リリース戦略
メリットとデメリット
👍動作検証を行うトピックブランチを切り替える度に、マイグレーションをリセットしなくてよい
👎複数のトピックブランチで同じDjango Appにマイグレーションを追加している場合、 manage.py makemigrations --merge が必要になる。このコミットを検証用ブランチに直接う行うため、「トピックブランチにもmasterにも含まれないコミット」が発生する。そして多くのトピックブランチがacceptanceにマージされてくると、次第に何がどうなってるのか分からなくなってくる。
👎acceptanceに溜まった「不要なコミット」を掃除するため、定期的にacceptanceを破棄して、masterから作り直す必要がある。このとき、検証中ブランチがゼロ、ということはまずないので、acceptance破棄後に「必要なトピックブランチをマージしなおす」。必要なトピックブランチがどれだったか把握するには、CHANGELOGが重要となる。masterのCHANGELOGと、破棄前のacceptanceを見比べて、acceptanceにマージするべきトピックブランチを把握する。
acceptanceブランチを導入するのはだいぶ覚悟が必要。
戦略4: モデル変更の先行リリース導入(+戦略3)
目標: CHANGELOGの競合をなくそう、acceptanceの再作成を楽にしよう
ブランチ戦略
master + トピック + acceptance
変更内容を CHANGELOG.rst に書く代わりに changelog/1234.feature.rst といった個別のファイルに書いておく。
https://gyazo.com/708d4b951957326ac29e542dd1025451
リリース時に towncrier でchangelog/以下のファイル、タグ、日付から CHANGELOG.rst を自動生成する
https://gyazo.com/93e7c9eafee69ff799d137788bf66b56
マージ戦略
リリース戦略
メリットとデメリット
👍 CHANGELOG.rst自体のマージコンフリクトが起こらなくなる。
👍 acceptanceブランチに何がマージされているのか把握するのが楽になる。 changelog/ 以下のファイルがどのブランチからやってきたのか把握するのは、CHANGELOG.rst の更新履歴を追うより簡単。
戦略5: developブランチの導入(+戦略4)
目標: 本番へのhotfixを可能にしよう
ブランチ戦略
master + develop + トピック + acceptance
マージ戦略
リリース戦略
メリットとデメリット
戦略6: モデル変更の先行リリース導入(+戦略5)
目標: マイグレーションの競合をなくそう
ブランチ戦略
master + develop + トピック + acceptance
マージ戦略
モデル変更は実機能の実装前でも、早々にmasterへマージ&リリースする。
リリース戦略
メリットとデメリット
個別の話題1: rebaseによる運用
メリットとデメリット
👍トピックブランチをマージ前にrebaseするのは、Git操作の技術的な難易度が高いものの、そのブランチに含まれる差分は全て自分がその機能実装のために書いたコードだと言え、PRでレビューしやすい状態を維持できるため良い結果を得られやすい。また、親ブランチをトピックブランチにマージする運用よりもソースコードの履歴グラフがキレイになるメリットがある。キレイになるというのは見た目だけの問題ではなく、なにかコード修正による動作の問題が起きたときに、発生原因を追跡しやすい。
👎Gitにだいぶ慣れてないと、rebase で時間をくったりブランチぶっ壊したりするので、rebaseは人類には早い、という気持ちになる。
👎検証用ブランチを導入している場合、検証用ブランチへのマージ後にリベースを行うと問題になる可能性が高い。トピックブランチをどこかにマージする前であればrebaseをしてもよいが、マージ後にrebaseして、そのマージ先に再度マージする必要があると、既にマージ済みのコミット差分がもう一度マージされる可能性がある。このとき、その差分に含まれるコード片が2回ソースコードに登場したり、異なる位置に登場したり、といったコード破壊が発生する可能性がある。
rebaseする場合、検証用ブランチなしで、ブランチの生存期間を短め(2週間以内)にしたい。
個別の話題2: マージ済みmigrationファイルの修正
マージ前のトピックブランチで、生成済みmigrationファイルを書き換えたり作り直したりすることは、たまにある。
誤ったマイグレーションを修正したり、試行錯誤した結果複数に分かれてしまったマイグレーションを1つにまとめたりする。
しかし、acceptanceブランチへのマージが既に行われている場合、マイグレーションファイルの書き換えを行うと地獄がまってる。既にacceptanceブランチを適用した検証用環境では、書き換え前のマイグレーションが適用済みのため、ここで不整合が起こってしまう。検証用環境への再リリースでマイグーレションを行おうとしてエラーが起こると、その原因を調べるのに半日かかったりする。