どうも、@infoengine1337です。つい一か月ほど前に、Gitを使った開発を始めました。それ以前はGitもGithubもあまり使ったことがなく放置だったのですが、ついにです。しかしそれを用いた開発を進めていくうえでいろいろ運用方法を見直していかないといけないと思ったことがあり、それの備忘録と他人にそれをチェックしてもらいたいという心でこの記事を執筆します。
※注意点
この記事はGitを使い始めて一か月の素人が執筆しています。間違ったことやよろしくないことがあった場合はマイルドなマサカリを投げてくださるとうれしいです。
追記
コメントで「それはGitFlowそのものではないか?」というご指摘をいただきました。個人的にはmasterやdevelopなどの変更を集約するブランチは長命に(Git-Flow的な思想)、変更を積み重ねていくブランチは短命に(Github-Flow的な思想)という使い分けをしていたつもりだったのですが、実際Git-Flowとそれほど変わっていなかったのかもしれません(?)
まだ理解がうっすらとしているので、ご指摘大歓迎です。
まず結論から
ブランチを二種類に分ける
チーム開発をするうえで必要なブランチを「コアブランチ」と「部門ブランチ」という二種類の概念に分けて管理。
コアブランチ
- master
- develop
- releases
ブランチなどといった、主に統合ブランチを担うもの。マージされる側で、基本的にはこのブランチでマージコミット以外のコミットを積み重ねることのないようにする。
部門ブランチ
- features/**
- hotfix/**
ブランチといった、主に特有の機能やバグ修正といった細かい一部門の変更を施すもの。基本的に変更したい内容ごとにfeaturesやhotfix下にネストを作成してそこにコミットを積み上げ、それをコアブランチ(developが好ましい)にマージすることを目標とする。
思想として、その一部門毎にブランチを作っては投げ、作っては投げなので、
短期間で機能を作ってpush、あとはブランチを削除する…という流れが一番好ましい。
短命なブランチとも呼ぶべきか。
コアブランチ・部門ブランチ別の運用方法
コアブランチ
- ブランチの作成は必ずGithub上(リモート)で行う
- ローカル環境でコアブランチへの部門ブランチのマージは絶対にしない
- つまり、コアブランチにマージしてpushすることは厳禁
- 常に最新が好ましく、ローカルブランチは時間が経ったらfetch & 追跡ブランチからmergeすること(要するにpullすること)
部門ブランチ
- 部門ブランチの作成はローカルで行って良い
- 部門ブランチの内容をローカルでコアブランチにマージすることは厳禁
- あくまでもそのブランチをそのままpushすること
- 短命であるため、masterの内容をmergeしてくることは基本的には避けるべき
- 前述のとおり、用が済んだら削除される、短命なブランチであるということを忘れずに。
- 要するに、masterの最新の姿を見る間もなくmasterにマージされ、消えていく
部門ブランチの内容が完成したらまずはローカルでマージはせずにそのままpush。
そしてそれがGithub(リモート環境)であがり、それをプルリクエストする。
それがマージされたのを確認して管理者がちゃんとブランチを削除する。
そしてプルリクを投げた(部門ブランチを作った人)も部門ブランチをローカルから削除する。
コンフリクトが発生したときは、その場で解消してマージ。コンフリクトが発生する→そのブランチが派生した時点でのコアブランチと現在のコアブランチにラグが生じているということ(だと個人的に解釈している)なので、この場で最適解となるようにコンフリクトを解消してしまう。部門ブランチは削除されるため、今後気にする必要はない。
何故この方法を考えたのか
うまく言語化できない点をご了承いただきたい。
- チーム開発をするにあたって無視できない点として、「自分がブランチを切って開発をしている最中に、ほかのチームメイトがどんどんマージしてコミットを進めてしまう」といった点があるように感じたから
- 一つのブランチを更新しながら使用し続ける運用方法にヒヤヒヤしたものを感じたから
- 後、ブランチのマージ方法について確固とした運用方法が共有されていないのではないか?と感じたから
以下ポエム
自分が例えばmasterからブランチを切って開発しているときにほかの開発者がmasterにコミットをマージしてどんどん開発を進めていたなら、自分が切ったブランチをpushするときにmasterのマージが必要になる・もしくはmasterへのPRをmergeするときにコンフリクトが生じて、その場でコンフリクトしないような修正を迫られるだろう。リモートでコンフリクトを修正してmergeしたとしても、今後そのブランチをローカルで使い続けていくとすればブランチは古いままで、masterに施された開発は一向に反映されない。また、masterをpullしてその開発ブランチにmergeするとなるとマージコミットが発生してしまい、その結果Gitログが汚くなるといった点もあるような気がする(要検証)。最新のmasterを取り入れたいという目的があるがためにマージコミットというジョイントのようなコミットをチェーンに取り入れ、その状態でpushをしていくのは少し危なっかしいのではないか??と思ったりした。それぞれの部門を別ブランチにして毎度生やしたほうが綺麗な運用になるのでは?と思ったところもある。それより新陳代謝を活発化するかのごとく、新しいブランチをどんどん生やし、古い用済みのブランチをどんどん棄てていってしまえば??との発想。まあリベースマージという選択肢もあるのかもしれないが、その場合もっと悲惨なことになりかねないのでは??とかも考えた。
また機能を増やす点ではブランチを細分化して堅牢さよりも作業の高速化を図るが、コアブランチではまったく態度を逆にし、しっかりとした運用が必要なのではないか?との考えに達した。他のブランチからのマージは完全にリモートのみで行い、ちゃんと実態の可視化ができるようにするべきで、ローカルでブランチを弄くるとろくなことにならないという印象があり。サイトの解説によってはコアブランチ達をローカルのGitコマンドやGitクライアントで弄ったりしているが(ローカルでトピックブランチの内容をmergeしてmasterをpushしてるサイトもあった)、そういう事をしないためにもちゃんとブランチはリモートにもっていき、リモートでmergeしよう、というような考え方がいいんじゃないかなと思っている。何かもっと深い意味があったような気がするが忘れた…すいません!!!
終わりに
「コアブランチ」「部門ブランチ」というのは完全な自分の造語です。また、ブランチの命名はGit-Flowを参考にしました。いろいろ考えて疲れました。もし意見や批評などありましたら、やさしくマサカリをください。Gitのシステムを完全に理解しきれていないので、Gitの裏で起きていることの勉強も頑張ります。よく考えるとGitの管理方法とブロックチェーンって少し似てる部分ありませんか??みたいなことを思ってます。