Github Flow
チームソフトウェア開発のためのワークフロー
チームでソフトウェアを開発するとき,チームメンバーがバージョン管理システムをどのように利用するかは非常に重要な課題である.各メンバーが好きなようにコミットを行い,勝手に開発をすすめるようなことになれば,完成したソフトウェアがどこにあるのか分からなくなったり,開発中のソースコードが完成版のソフトウェアに紛れ込んだりといった様々な問題が発生してしまうことになる.
そのため下記のように,版管理システムの利用ルールを決めたチームソフトウェア開発のためのワークフローが数多く提案されている.
- Gitの開発者らによって提案されているGit-flow
- Gitlab1と呼ばれるgitリポジトリのホスティングツール・サービスの開発者らによって提案されているGitlab flow
- 本演習で対象とする同じくgitリポジトリのホスティングサービスGithub2の開発者らによって提案されているGithub Flow
これらのワークフローでは,チームでのソフトウェア開発の様々な局面において,各メンバーがどのように版管理システムを利用・操作するべきであるかが示されている.本演習では既存のワークフローの中で最もシンプルなものの一つとされているGithub Flowについて紹介し,演習を行う.本節ではGithub Flowの6つのルールと関連するGitリポジトリの操作について説明する.
Github Flowにおける6つのルール
Github FlowとはGithubの開発者によって提案された以下に示す6つのルールから構成されている非常にシンプルなワークフローである.以降に示すルール及びその詳細はGab-km氏によるGithub Flow(japanese translation)にもとづくものである.
master
ブランチにあるものは何でもデプロイ可能である- 新しい何か(機能追加やバグ修正などなんでも)に取り組む際は,説明的で分かりやすい名前のブランチを
master
から作成する - 作成したブランチにローカル(開発者のマシン)でcommitし,サーバー上にも定期的に作業内容(commitしたもの)をpushする
- フィードバックや助言が欲しいとき,あるいは作成したブランチでの作業内容を
master
ブランチにmergeしても良いと思ったときは,Pull Requestを作成する - Pull Requestは自分以外の誰かがレビュー(作業内容の確認)をしてOKを出してくれたときのみ
master
ブランチにmergeしてよい - mergeをして
master
へpushしたら,直ちにデプロイをする
以降では各ルールについて詳述する.
ルール1:master
ブランチにあるものは何でもデプロイ可能である
デプロイとはソースコードをアプリケーションとして正常に実行された状態に処理し,配備することを示す.例えばWebアプリケーションの場合,ソースコードをコンパイルし,Webアプリケーションリソースとしてまとめ,アプリケーションサーバのしかるべきところに置き,アプリケーションサーバを必要に応じて再起動する.これによってWebアプリケーションとして利用できる状態になる.このような一連の操作のことをソフトウェアのデプロイ(配備)と呼び,デプロイ可能とはソースコードをデプロイによって正常にアプリケーションとして利用可能な状態にすることができることを表す.
Gitではリポジトリ作成時にmaster
と呼ばれるブランチが作成される.
ルール1はこのmaster
ブランチにあるソースコードが常にデプロイできる状態であることをチームに対して求めている.
上図に示すようなリポジトリがあるとする.ここではある開発者がローカルリポジトリを作成し,何らかの開発作業を行い,ローカルリポジトリにCommitを行った後,そのリポジトリをGithub(リモートリポジトリ)にPushしている.同じように複数の開発者がmaster
ブランチにCommitし,Pushした結果,初期Commit(リモートリポジトリmaster
ブランチの一番左の灰色の丸)から右に3回のCommitが行われている.
ここで2つ目,3つ目,4つ目のCommit終了時にリポジトリ内のソースコードをCompileし,Runしてみると,2つ目と4つ目はソフトウェアが正常に動作したが,3つ目ではエラーが発生し,正常に動作しなかった.
ルール1では,このようなmaster
ブランチに対して行われたCommitの結果,ソフトウェアが正常に動作しない状態になることを禁止している.すなわち,master
ブランチにあるソースコードは常に正常に動作することを保証することで,開発途中のソースコードや正常に動作しないままのソースコードがmaster
ブランチに混じらないようにするべきであると示している.
本演習ではProcessingを用いて開発を行うため,ソースコードが正常にコンパイル可能であり,実行時エラーが発生するようなことがなければ正常に実行が可能である.そのため,本演習におけるルール1はmaster
ブランチにあるソースコードは常に正常にコンパイル可能であり(コンパイルエラーが発生しない),実行可能であり(実行時エラーが発生しない),チームの意図した機能が意図した仕様で動作することを維持し続けることを目指すものとする.
実際にこのルール1を守るためには,master
ブランチに対して開発者がいきなりCommitを行うようなワークフローでは難しい.そのため,開発者によるCommit内容を他の開発者が確認し,問題なければmaster
ブランチに取り入れるといったフローが必要となる.
ルール2:新しい何か(機能追加やバグ修正などなんでも)に取り組む際は,説明的で分かりやすい名前のブランチをmaster
から作成する
デプロイ可能なmaster
ブランチのソースコードに対して機能追加やバグ修正,あるいは可読性を改善するためのソースコードの修正(コメントをつける等)等を行う際,ルール1で示したようにmaster
ブランチに対して直接手を入れるようなことをしてはいけない.
上図が示すようにGitではリポジトリ作成時に生成されるmaster
ブランチ以外にもブランチを自由に作成できる.ブランチによって元のソースコードに影響を受けない開発履歴を保存することが可能となる.この例の場合,add_cpu_logic
ブランチでのCommitはmaster
ブランチに影響を及ぼさない.そのため,Gitを利用した開発では通常,バグ修正や機能追加といった新しい開発作業を始めるたびにブランチを作成する.
自由に作成できるブランチだが,Github Flowではその作成において,一定のルールを定めている.それは,必ずmaster
ブランチから新しい説明的で分かりやすい名前のブランチを作成することである.例えばuser-content-cache-key
,menu-behavior-act-i
等のような追加する機能や編集する機能の名前,モジュール名などが分かりやすくつけられていることが望ましい.
上図の例の場合,master
ブランチから作成したadd_cpu_logic
ブランチは問題ないが,add_cpu_logic
ブランチから分岐して作成したtemp
ブランチはmaster
ブランチから作成されたものではない.ブランチは自由に作成できるが,そのようにして作成されたブランチは最終的にmaster
ブランチに取り込む(mergeと呼ばれる)必要がある.そのとき,master
ブランチ以外から作成されたブランチが存在すると,そのmerge作業が非常に困難になる.
また,この例の場合,temp
ブランチという名前も望ましくない.Github Flowにおいてブランチを新たに作成する場合は,そのブランチが何を目指したものなのかが第3者にも分かりやすいような命名を心がけるべきである.
ルール3:作成したブランチにローカル(開発者のマシン)でcommitし,サーバー上にも定期的に作業内容(commitしたもの)をpushする
ルール2で作成するブランチはそのままではローカル(すなわち開発者のマシン)のリポジトリ内にしか存在しないため,チームの他の開発者には誰がどのようなブランチを作成したかは分からない.そのため,Github Flowでは,ブランチ作成時あるいは開発作業中(すなわちブランチに対するcommitが行われている際に)に開発者が作成したブランチをサーバーへpushすることを指示している.ここでcommitとは既存のソースコードに対して行った編集内容をリポジトリに登録することを指し,pushとはローカルリポジトリの内容をサーバ側リポジトリにアップロードし,同期させることを示す.
開発作業中のものも含めて,すべてのローカルリポジトリで作成されたブランチをpushすることにより,現在誰が何をしているのかをサーバ側のリポジトリにあるブランチリストを見るだけで把握することが可能となる.
例:Githubで開発されているDeveloperツールのブランチリスト
上図の例では,開発者A,Bがそれぞれ異なる機能を実装している.ブランチ作成時及びCommit後にPushを行うことで,ローカルリポジトリで作成したブランチがリモートリポジトリに登録される.結果として,赤枠で囲まれたようにどのブランチが現在開発されているかをチームの全開発者が容易に理解できるようになる.
ルール4:フィードバックや助言が欲しいとき,あるいは作成したブランチでの作業内容をmaster
ブランチにmergeしても良いと思ったときは,Pull Requestを作成する
ルール1において,master
ブランチに直接Commitすることは望ましくないと述べた.そのためGithub Flowでは,ルール2及び3でmaster
ブランチから作成したブランチの内容をmaster
に取り込むために,Pull RequestとMergeと呼ばれる機能を利用する.
Pull Requestは以下のような機能であると述べられている.
プルリクエストとは簡単に言うと、開発者のローカルリポジトリでの変更を他の開発者に通知する機能です。プルリクエストは次のような機能を提供します。
機能追加や改修など、作業内容をレビュー・マージ担当者やその他関係者に通知します。 ソースコードの変更箇所をわかりやすく表示します。 ソースコードに関するコミュニケーションの場を提供します。
上図の例では,開発者Aがrecord_result
ブランチにCommit後,Pushを行い,リモートリポジトリにもrecord_result
ブランチの開発内容をアップロードしている.その後,点線で描かれているように,record_result
の内容をmaster
ブランチに取り込んでも良いか(Merge)を他の開発者に確認してもらうために,Pull Requestを作成している.
Pull RequestはGithubの機能として実現されており,Github Desktopと呼ばれるGitクライアントやGithubのページから作成できる.他の開発者は作成されたPull Requestを見ることで,record_result
ブランチで何が行われたのかを把握することができる.また,必要であればrecord_result
ブランチを別の開発者が自身のローカルブランチに取り込み,動作確認を行うことも可能である.
なお,Pull Requestはrecord_result
ブランチの開発が完了していなくても作成して構わない.その場合は,取り込み(Merge)が目的ではなく,実装内容を他の開発者に診てもらうことそのものが目的となる.
ルール5:Pull Requestは自分以外の誰かがレビュー(作業内容の確認)をしてOKを出してくれたときのみmaster
ブランチにmergeしてよい
ルール4で作成したPull Requestは自分以外の誰かに必ずレビュー(作業内容を確認してもらうこと)してもらった後に,master
ブランチにマージできる.すなわち,自分以外の誰か他の開発者が,Pull Requestをチェックし,その作業内容をmaster
ブランチに統合(merge)しても問題ないと判断してはじめて,mergeを行うべきである.
このルールはルール1にあるmaster
ブランチは常にデプロイ可能であることを保証するために存在する.複数の開発者が好き勝手にmaster
ブランチの内容を修正するのではなく,少なくとも2人以上の開発者が確認した後mergeを行うことで,master
ブランチにバグが混入しにくくなる.
この図にあるように,Pull Requestが作成され,他の開発者によるレビューが完了してはじめて,Mergeを行い,record_result
ブランチの内容をmaster
ブランチに取り込むことができる.Githubでは問題がなければPull Requestの画面からMergeを行うことができる.
ルール6:mergeをしてmaster
へpushしたら,直ちにデプロイをする
ルール4,5で述べたPull Request機能によって,ある開発者が開発した機能はmaster
ブランチにmergeされる前にチェックされる.しかしながら,その場合でもバグが混入することがありうるため,master
ブランチへのmergeが行われた時は,その直後に必ずmaster
ブランチの内容が正常にデプロイできるかどうかをチェックしなければならない.
本演習の場合は,下図が示すようにmaster
ブランチへのmerge後にmaster
ブランチを取得(Pull)し,正常にコンパイル・実行がProcessing環境上で可能であることを確認することを指すものとする.
以降では,本演習で利用するProcessing環境について説明した後に,上記の6つのルールにもとづいた開発をどのように行うかについて,簡単なゲーム開発を題材に演習を実施する.
問題
Github Flowはチームでバージョン管理システムを用いて開発をする上で発生する様々な問題を改善するためのルールを提供している.具体的にどのような問題が改善されるか,2つ以上の問題について述べよ.まず問題について説明し,その問題をGithub Flowのルールがどのように改善してくれるのかを記述すること.