チーム開発におけるGithubのブランチ運用(wipブランチの活用)


ブランチ運用のナレッジが溜まってきたので、まとめてシェアします。
現場ごとにいろいろ考え方があると思うのですが、自分がやっていて合理的だと感じている活用を書きます。

チーム開発でのPR WIPブランチの活用

大体の開発はタスクの中に子タスクがあることがほとんどなので、コードレビューをしてもらう際はタスクを切り分けてPR(プルリクエスト)を出していくとよい

たとえばこんなタスクを開発する時、

あるステータスのユーザーにはアイコンに青いバッジをつける (wip)

子タスク1 プロフィールのアイコンにバッジをつける (子1)

子タスク2  Cardのアイコンにバッジをつける (子2)

子タスク3 アイコンの名称の翻訳を17か国語で入れる (子3)

WIP branchを使おう

WIPブランチは細かいタスクをまとめたブランチのような、空っぽのフォルダのような存在。WIPとはwork in progress。

リリースブランチに直接PRを出していくより、リリースブランチと差分のないwip ブランチのような空のブランチにPRを出す方がレビューの時、自分の開発した差分だけを相手に見せやすくなる。

WIP branchを作るメリット

  • タスクを小分けにすることでdiff(差分)が見やすいのでレビュワーにミスに気付いてもらいやすい
  • 小さいタスクごとに開発するので進捗が可視化されやすい
  • 開発に着手し始めたことがチームに伝わりやすい(最初のcommitまで時間がかかる時、PR が作成されるのに時間がかかってしまい、いつ開発が始まったかわからない)
  • 複数の開発者で子タスクの分担がしやすい

wip branch(空っぽ)に

  • change_requirement_project_button
  • add_multiple_notification
  • change_layout
  • add_translation
  • fix_template

のような子タスクbranchを切ってPRを出していく

一つずつ開発してLGTMをもらったら空っぽのwip branchにどんどん入れていく。

wip branchの向き先はreleaseのためのブランチになる

WIP を使った開発でのbranchの向き先の例

masterrelease_branchwip/add_somethingadd_something_1 add_something_2

なぜメリットが大きいのか → PRに自分が開発した場所のdiff(差分)だけがはっきり出るから

wipに向けて複数の子ブランチへPRを出していくと、release_branchに直でPRを出すよりも良い

  • 他の誰かが先にrelease_branch にコードをmergeしてもwipとその子ブランチに無駄なdiff(差分)が生まれない。
  • wipに紐づいたタスクが2つある場合、add_something_1add_something_2を2人の開発者で分担する時、それぞれの開発の変更が干渉し合わないので、diff(差分)がみやすくなる

空コミットの方法

普通、コードに何も変更のない場合commitはできず、リモートへpushできない。

ただし、これを使うと空commitができ、リモートへpushすることができる

git commit --allow-empty -m "wip commit" 

子branchの開発が終わり、LGTMもらったら?

wipにmergeして子branchは消しておく。気づくとリポジトリ内にめっちゃ溜まってる...

github チーム開発における基本のワークフローをざっくりまとめる

まず開発を始める時にローカルでwip(例:wip/something)と子ブランチ(例:new_cool_feature_branch)作成

git checkout release/0.0.1 //新しいreleaseブランチなどコードが最新のブランチに移動
git checkout -b wip/something // releaseブランチからwipブランチをcheckout
git checkout wip/something // wipに移動(このコマンドを打たなくても多分もう移動している)
git commit --allow-empty -m "wip commit" // 先述のように、空のコミットをします
git push origin wip/something // wipをリモートにpushしてgithub上でcreate pull requestします

// 子ブランチを作る
git pull origin wip/something // wip ブランチを最新にします
git checkout -b new_cool_feature_branch // 子ブランチをcheckoutします

これで子ブランチにて開発を進めます

開発中のコミット

git commit -m "Add layout" // add とか fix とか remove とかわかりやすいメッセージにする
git commit -m "Add logic"
git commit -m "..."

子ブランチをPRする時

git checkout wip/something // **一旦wipに移動します**
git pull origin wip/something // PR前に必ずwipが最新にする!(余分な差分を生まないため)
git checkout new_cool_feature_branch // wip ブランチから new_cool_feature_branch(子ブランチ)へ移動
git merge wip/something //  他の人が別の開発をmargeしたためwipが最新ではなかったので、wip/somethingの内容をnew_cool_feature_branchに**merge**
[ここでコンフリクト出たら修正]
git push origin new_cool_feature_branch // 子ブランチをリモートへpush

ポイントは、PR前に一旦必ずwipの方を最新にすること。

そしてそれを子ブランチにmargeしておくこと。

wipの最新の内容を子branch (new_cool_feature_branch)にmargeせずをpushするとコンフリクトになることがある。

gitでのコンフリクトによるミスを防ぐために意識すること

  • 1, merge時は必ずリモートの変更を優先する気持ちでいる(他の誰かのコードを消してしまうとかなり大変)
  • 2, ローカルエディターで両方の変更を取り込む選んで、気をつけて手動で直す
  • 3, github上でコンフリクトを解消しない(直したコードが動くかどうか確認ができないまま,mergeすることになるから)

子 branch[wip]branchにmergeしたい時、コンフリクトが起こった場合、

  1. エディタでまずは両方の変更を取り込む
  2. 必要ないコードを確認しながら編集する (スーパーウルトラダブルチェック)
  3. その状態で自分の開発環境でbuildしてエラーが起こらないかチェックする。
  4. 解決したコードを子 branch にpush
  5. [wip]branch にmerge

ポイントはコンフリクト解消後は自分の開発環境でbuildしてエラーが起こらないかチェックすること

これで、コンフリクトの解消に万が一ミスったとしても、エラーに気付けることが多い

テストしたい時のコンフリクト

integration環境で自分が開発したところをテストしたい! しかし、

integrationブランチ(test環境)に自分の開発をpushしようとするとコンフリクトが発生するとき

いつものようにこのプロセスでintegrationに今回のリリース用の開発をデプロイしようとしたらコンフリクト発生

1. // ローカルのintegrationとrelease/branchを最新にする
2. git checkout integration //integrationブランチへ移動
3. git merge release/branch // integrationブランチに今回のリリースブランチの内容をmergeする
// [コンフリクト発生😭]
4. git push origin integration

integrationブランチにこれからreleaseする内容をdeployしようとしてたくさんコンフリクトが発生する場合、それを直すより integrationブランチを作り直した方が早いかもしれない。

→ 誰がどんな変更をintegrationに加えたか全ては追いきれないため。

git branch -D integration //今あるローカルのintegration branchを一旦**-D**で消します
git checkout release/0.0.1 // 今の最新のbranchに移動
git checkout -b integration // 新しくintegration branchを作り直します
git commit --allow-empty -m "deploy commit" // リモートに空コミットをします
// [他の人のwipブランチがあればマージする] // テストしたい開発をこのタイミングでマージします
git push -f origin integration // -fつけてリモートにpushします

しかし毎回作り直しを行うと、他の人がテストしている場合、適用されていたものを消してしまう。他の人がテストをしていない時にコンフリクトした場合だけ、integrationブランチを新しく作成するとよい。作り直していいかチームに確認を取ること。

大事なこと

レビューしてくれる人に差分をわかりやすく伝える気遣いが大事

wipを使うとわかりやすくタスクを細分化すると進捗が整理されやすい

デプロイするときコンフリクト起こると焦るけど、落ち着いてダブルチェック。慣れないうちはgithub上でのコンフリクト解消機能は使わず、ローカルでちゃんと動作するか確認してからデプロイする