torutkのブログ

ソフトウェア・エンジニアのブログ

Githubのブランチ管理方針~Redmineプラグインの場合

Gitのブランチ管理方針~Redmineプラグインの場合

Redmineプラグインのコード管理の背景

RedmineのGlossary Pluginをフォークして細々とRedmineバージョンアップに対応しています。

https://github.com/torutk/redmine_glossary

Redmineプラグインのコードを管理する上で、ターゲットとなるRedmineバージョンを明確にしておくことはとても重要なことです。 というのは、Redmine本体がバージョンアップする際に、RedmineがベースとしているフレームワークであるRuby on Railsをメジャーバージョンアップした場合、プラグインにも大きな変更が必要になるからです。

Ruby on Railsはバージョンアップに対して後方互換性を考慮することはあまりなく、APIの廃止、変更がばしばしと入ってきます。そのため、RedmineプラグインRuby on Railsのメジャーバージョンアップに対応させるには、プラグインのコードにAPIの廃止と新しいAPIへの移行を行うなどの修正を入れていきます。

Redmine 3.4(Ruby on Rails 4.2)からRedmine 4.0(Ruby on Rails 5.2)へのバージョンアップに際してプラグインの修正が必要となった非互換性については一昨年に次の記事にまとめました。

Redmine 4.0(Rails 5.2)に用語集(Glossary)プラグインを対応させる - Qiita

これらの修正では、同じコードでRedmineの旧バージョンと新バージョンに対応することが困難であり、あきらめてRedmine 4.0向けとしました。もし、ひとつのコードで複数のRedmineバージョンに対応するためには、if文でRuby on Railsのバージョンをチェックして新旧の双方のコードを記載するなど、そうとうに煩雑なコードになりそうでした。

そこで、一つのコードで複数のRedmineバージョンに対応するのをあきらめて、Redmineの各メジャーバージョンに合わせてプラグインのコードを分けることにします。ただし、プラグインのコードを分けて管理するには、複数のブランチでリリースを管理することになります。

いままでは、ブランチ管理方針を考えることなく、その場その場で適当にブランチを作成していましたが、これからは混乱しないようにブランチ管理方針を決めてコードを管理していきたいと思います。

Gitのブランチ管理方針を調べる

Git でよく見かけるブランチ方針「A successful Git branching model」は、masterブランチにリリースしたバージョンのタグを打って管理し、releaseブランチはリリース作業中の一時的なブランチとし、リリース準備が完了するとreleaseブランチからmasterブランチにマージを行い、リリースタグを削除します。この場合、新しいバージョン(例:Ver.2.0.0)をリリースした後に、前のバージョン(例:Ver.1.4)の修正をして前のバージョンのマイナーバージョンアップ(例:Ver.1.4.1)をすると、masterへの反映ができなくなってしまいます。

この「A successful Git branching model」に基づいていると思われる「Git flow」というワークフローでは、オプションとしてsupportブランチを設け、master以外に古いバージョンを管理する場合に使用するようになっています。 supportブランチは、リリース後の管理をするためのブランチなので、リリース準備をするreleaseブランチとは別に設け、releaseブランチで準備が完了しmasterへマージをした後に、masterからsupportをブランチさせて使用します。

以下はGit flowで使われるブランチとその概要です。

  • master リリースしているコードの最新。常に1つ。直コミット厳禁でリリースブランチあるいはhotfixブランチからマージによってのみ更新。
  • develop/xxx 開発中のコード。複数のdevelopブランチが並走することがあり、スラッシュに続いてバージョン名を記した命名をする。直コミットも可(1回のコミットで完了しない変更はfeatureブランチを設ける)。
  • feature/xxx 複数のコミットで完了する大掛かりな開発はいったんfeatureブランチを設けてそこへコミットし、完了後にdevelopにマージする。スラッシュに続いて開発コード名(あるいは目指すバージョン番号、開発チケット番号等)を記した命名をする。
  • release/xxx リリース準備をするコード。スラッシュに続いてリリース番号を記した命名をする。リリース準備が完了したらmasterにマージする。masterにはリリース番号のタグを付与する。masterにマージ後そのreleaseブランチは削除する。developに反映したい場合は、masterからdevelopへマージする。
  • hotfix/xxx masterに素早く変更を加えたい場合に、masterからブランチし、masterおよび必要があればdevelopへマージする。xxxはバージョン番号(マイナーバージョンあるいはマイクロバージョン番号を更新したもの)など。
  • support/xxx 過去のバージョンのサポート。リリースしたmasterからブランチし、サポート期間中維持する。

Redmineのバージョンと利用状況

プラグインの保守対象バージョンを判断するには、Redmineの各バージョンがどの程度使われているかを知りたいところです。 年に2回実施されているRedmine.tokyo勉強会では、使用しているRedmineのバージョンなどが参加者アンケート集計結果として公開されています。

Redmine.tokyo 17 questionnaire

2019年11月の場合では、Redmine 4.0が25%弱、3.4が40%弱、3.3~3.0が20%弱、2.6~2.0が10%弱といった分布です(目分量)。

勉強会参加者なので、比較的新しいバージョンを使う動機の大きい人たちという点を考慮に入れても、Redmine 2.0以降のバージョンは現時点では対象と考えておくのがよさそうです。

Redmineのバージョン、Ruby on Railsのバージョン、Rubyのバージョンの関係は次となります。

Redmineバージョン Ruby on Railsバージョン Rubyバージョン
4.0, 4.1 5.2 2.2.2, 2.3, 2.4, 2.5
3.4 4.2 1.9.2, 1.9.3, 2.0, 2.1, 2.2, 2.3, 2.4
3.3 4.2 1.9.2, 1.9.3, 2.0, 2.1, 2.2, 2.3
3.0 4.2 1.9.2, 1.9.3, 2.0, 2.1, 2.2
2.5.2 3.2 1.8.7, 1.9.2, 1.9.3, 2.0, 2.1
2.3.0 3.2 1.8.7, 1.9.2, 1.9.3, 2.0

そこで、supportブランチの下には

| ブランチ名 | 対応Redmine | |++|++| |support/2.x | Redmine 2.3, 2.5 |support/3.x | Redmine 3.0, 3.3, 3.4 | |support/4.0or1/based_original | Redmine 4.0, 4.1 |

の3つを用意します。Redmine 4.0および4.1への対応は、これまでのコードを修正して対応するバージョンと、ゼロから作ったバージョンとがあり、これまでのコードの修正をsupport/4.0or1/based_originalブランチで行っています。ゼロから作り直しは現在developブランチで行っており、最初のリリースをmasterにマージしています。

このブランチの見直しがリポジトリに入っています。