Michi's Tech Blog

一人前のWebエンジニアを目指して

今さら「Gitflow」の復習

こんにちは!
スマレジ テックファームのMichiです!

今回はGitflowの復習がてら、記事を書きます。

今更Gitflowを学ぶ理由

「エンジニア歴9カ月目で今さらGitflowの復習?」と思われるかもしれませんが、これにはちょっとした事情があります。
エンジニアに転職して最初の半年は、先輩と2人で新規開発案件を担当していました。 メンバーが2人しかいないのでGitの運用も超適当で、特にブランチなども切らずに同じ場所で作業していました。

それでも、

僕「先輩、ここコンフリクトしたんですけどどうしたらいいですか?」
先輩「あー、じゃあそっちの変更に合わせといて」
僕「了解です!」

みたいな感じで、お互いに確認すればよかったんで、その時は特に問題なかったんですね。
で、最近になって、メンバーが何十人もいる大きなプロジェクトにアサインされたんですが、ここで問題発生。

僕「やべえ、Gitflow全部忘れた🙄」

入社前にちゃんとGitflowの勉強もしたんですけどね…。半年も触らなければ人間、見事に忘れるものです(笑)
そういうわけで、ここでしっかりGitflowを復習して、忘れないように身に着けたいと思います!

Gitflowとは?

Gitflowとはチーム開発でGitを運用する際のルールのようなものです。
Gitflowでは目的に応じて複数のブランチを派生させ、最終的にそれらをマージ(合体)させることでプロダクト開発をしていきます。

Gitflow 概念図

Gitflowで使用するブランチ

main(master)

すべての原型となるブランチです。
masterというのは古い言い方で、今はmainと呼称するらしいです。プロダクトをリリースするときはこのブランチからリリースされます。このブランチ上で作業を行うことはありません。

develop

mainから派生した開発用のブランチです。
実際の開発作業はここからfeatureブランチを切って行うので、このブランチ上で作業を行うことはありません。

feature

developから派生する機能の追加・修正用ブランチです。
各機能の担当者はdevelopから各々のfeatrueブランチを切り、作業が終わればその内容をdevelopへマージします。尚、このブランチを直接mainへマージしてはいけません。

release

同じく、developから派生するプロダクトリリース用のブランチです。
リリース予定日が近づくと、developからreleaseブランチを切り、リリース準備(総合試験やバグ修正)を行います。リリース準備が終了すると、その内容はmainへマージされた後本番環境へデプロイされます。また、developへもマージされます。

hotfix

mainから派生する緊急対応用(バグ修正など)のブランチです。
このブランチのみ、mainから分岐します。作業が終われば、mainとともにdevelopへ修正内容をマージします。

実際の流れ

今回はプロジェクトの一メンバーとして、Gitflowを用いて開発する際の流れを解説します。
尚、プロジェクトにはすでにmasterdevelopブランチが存在するものとします。

1. developブランチを最新の状態にする

まずは大元となるdevelopブランチを最新の状態にします。

git checkout develop
git pull origin develop

2. featureブランチを切る

最新状態のdevelopからfeatureブランチを作成します。
ブランチ名はチームによりますが、例えばfeature/{#チケット番号}-{作業内容}のような規則で命名します。

git checkout -b feature/#123456-gitflow-test

3. featureブランチで作業を行う

作成したfeatureブランチで作業を行います。
作業内容は適宜コミットしましょう。

git add .
git commit -m "ADD:Gitflow test"

※次の項で述べますが、developブランチの変更を取り込む際にgit rebaseを使う場合は、ここでリモートリポジトリにプッシュしないように!

4. developブランチの変更を取り込む

最新のdevelopブランチを、現在作業中のfeatureブランチに取り込みます。
これは自分の作業中に、他のメンバーがdevelopに変更を加えた場合、自分の開発内容とコンフリクトを起こす可能性があるためです。

まず、developブランチに移動して、最新状態のリモートリポジトリを取り込みます。

git checkout develop
git pull origin develop

次にfeatureブランチに戻り、最新にしたdevelopを取り込みます。
ここでdevelopを取り込むには、mergereabaseを使う2種類の方法があります。

a. mergeを使用する方法

mergefeatureの先頭に、developブランチを合体させるコマンドです。

git checkout feature/#123456-gitflow-test
git merge develop

■特徴

  • featureブランチの先頭にマージコミットを作成する
  • 非破壊的な操作であるため、既存のブランチが変更されることはない
  • featureで長く開発を続けていると、開発機能とは直接関係ないマージコミットが増え続けてしまう

mergeのイメージ図(Bitbucketの公式ドキュメントより)

b. rebaseを使用する方法

一方、rebaseはコミットを新しく作り直すことによって、履歴を1本の線にするコマンドです。

git checkout feature/#123456-gitflow-test
git rebase develop

■特徴

  • コミットを作り直し、developブランチの先頭にfeatureの履歴をつなげる
  • 破壊的な変更であるため、ルールを守らないとチーム全体に影響を及ぼすことがある
  • マージコミットは作成されないため、履歴が直線的で見やすい

rebaseのイメージ図(Bitbucketの公式ドキュメントより)

ここで注意しなければならないのが、先ほども言ったようにrebaseする前にローカルの変更をリモートリポジトリ へプッシュしてはいけない」ということです。 rebaseはコミットを作り直すので、プッシュした後にrabaseを行うとローカルとリモートの内容に差異が発生し、コンフリクトしてしまいます。こうなるともう強制プッシュするしかないのですが、チームによってはGitHub/Labの設定によって強制プッシュが禁止されている場合もありますので十分気を付けましょう。

尚、mergeを使用するか、rebaseを使用するかはチームの方針によって変わってきます。わからない場合は、コマンドを打つ前に一度、ほかのチームメンバーに聞いてみるのがいいでしょう。

5. リモートリポジトリへプッシする

ここまで出来たら、ローカルのfeatureブランチの変更内容をリモートリポジトリへpushします。

git push origin feature/#123456-gitflow-test

6. マージ/プルリクエストを発行する

developブランチに対して、マージリクエスト(GitLab)、もしくはプルリクエスト(GitHub)を発行します。

7. レビューしてもらう

内容をレビューしてもらい、OKならリクエストが承認され、featureブランチがdevelopへマージされます。
指摘事項がある場合はコードを修正し、3. 以降の過程をやり直します。

まとめ

Gitflowの概要と実践について、サクッとではありますが解説しました。
「developブランチの変更を取り込む」 の箇所は、私も実務に入る前はmergeを使う方法しか知らなかったので、びっくりしました。(基本的にrebaeは使ったらアカンっていう認識のコマンドやった…)
初めて使う時は怖すぎて、先輩に「ほんまにやっていいんですか!?」って何回も聞いた記憶があります(笑)

参考

www.atlassian.com

www.atlassian.com