- 投稿日:
これは、かつて参画したGitHubを利用したプロジェクトでブランチフローが悪く事故が多発したので考案し、運用した内容です。
基本的には後々の運用を考えた時に情報源になり、かつGit操作に極力手間を取られることがなく、CI/CDを回しながら品質を維持できる内容で考えています。
フローの要件として考えたこと
取り回しが単純明快であること
開発以外の要素に振り回されないように単純なフローにしていて、世に言われる履歴の綺麗さとか言うのは個人的には関心が薄いので重視していません。その代わりコミットが壊れないことや、インデックスとして見やすくなるような部分を重視しています。
GitHubとの相性が良いこと
まず個々の開発タスクをIssueベースで管理し、Pull Requestベースで取り込む運用としました。
Pull Requestの取り込み方式はSquash Mergeとし、メインブランチのコミット履歴がPull Requestのマージコミットになるようにしました。
これはメインブランチのコミット履歴はPull Requestのマージコミットだけあれば後から追えるというのと、メインブランチのコミットログを単純にする意味でこの方式にしています。
CI/CDを活用しやすいこと
これは割とどこでもやっていると思いますが、ブランチ名にdevelop
とかstaging
, production
とか付けて管理することで、自動的に環境を識別できるようにしました。
実際に運用したフロー
フロー図
フローの運用内容
develop/main
ブランチを最新ブランチとする運用develop/main
ブランチ相当のものが複数ある状態というのが世の中にあると思いますが、管理が非常に大変なのでそれはしない方向にしました
- 機能ブランチを
develop/main
ブランチに取り込むのはSquash Merge- 基本的に変更履歴を見る時はGitLensや
blame
で変更行からPull Requestを当てて、そこを見に行くという運用にしていました
- 基本的に変更履歴を見る時はGitLensや
- 機能ブランチに
develop/main
ブランチを取り込むのはmerge
- 一般的には
rebase
が多いと思いますが、次の観点から採用しませんでした- どのポイントで取り込んだのかわからない
merge
と比較した場合にコンフリクト対応に手を取られる- 経験上ここで事故が頻発する
- 素直に
push
出来ない
merge
であれば以下のように単純な流れに出来ますし、push前に差分確認して事故を防ぐことも容易ですgit switch develop/main
git pull
git switch -
git merge -
- コンフリクトがあれば解消
git push
- 一般的には
- デプロイ方式によるルートブランチ分割
- ルートブランチ名によってデプロイ先を変更できるようにしました
- GitHub Actionsでブランチ名を拾って環境変数を差し替えることでデプロイするワークフローを組んでいます
staging/
やproduction/
ブランチはdevelop/main
からcheckout
する運用です- これらはデプロイするためだけの使い捨てブランチなので毎回生えます
あとがき
このフローの利点としてはマージでコンフリクトが起きても基本的にCurrentとIncomingを一回比較するだけで済むのでコンフリクトの解消が簡単で、コンフリクト時はIncomingが壊れないようにCurrentを直すのが基本になり、Currentを優先する場合は適宜上書きするといった内容です。
ブランチの合流はmerge
だとマージコミット分一回の解消だけでいいので事故の発生要因が低いのがrebase
と比較した時の利点です。rebase
だとコミット回数分再帰的に合流させる必要があるのでブランチの寿命が長かったりすると苦行になってきます。
このフローができた経緯としては元々はGitHub Flowをベースにしていたのですが、色々やっていくうちにこうしたらもっと良くなるのではないか?というのを試行錯誤していてこの形に落ち着いたのですが、後から調べたらGitLab Flowに近い形式に見えたので、似た内容は既に誰かが考えているものだなと感じました。
上で挙げた内容の他にもGitHubのリポジトリ設定でブランチ保護のルールを設定したり、Pull Requestのマージ設定でSquash mergingだけ許可したり、ヘッドブランチの自動削除をするなど、基本的に面倒なことを考えたり、しなくて良い様にするなど、開発に注力しやすいように環境を整えると心理的な抵抗が少なく運用できて便利だなと感じています。