第3章 Github Flow/Git-Flowを使った運用

git-flowの使い方

git-flowのコマンドと作業フロー

git-flowには開発、リリース、バグ修正用のブランチが用意されていて、それぞれに一連のフローがあります。それぞれほぼ同じ要領で作業を進められるので、おぼえる必要があるコマンドはかなり限られています。
これからそれぞれの工程を追って、リポジトリの準備から開発、リリース、バグ修正までの流れを説明します。

git-flowによるブランチ利用の流れ

git-flowにはブランチを作成するstartコマンド、ブランチを終了するfinishコマンド、共有リポジトリのコミットを取得するpullコマンドなどいくつかのコマンドが用意されています。

git flowのコマンド
コマンド説明
startブランチを作成
finishdevelop、もしくはdevelopとmasterへマージし、ブランチを削除
publishブランチを共有リポジトリで公開
track共有リポジトリからブランチを取得
pull共有リポジトリ上のコミットを取得
rebaseブランチ上でリベースを行う

git-flowはだいたい次のような書式になります。

git flow ブランチ種別 コマンド

ブランチ種別には開発・改修用であればfeature、リリース用であればrelease、バグ修正であればhotfixを指定します。

準備

git-flowのブランチモデル

git-flowでは、下記のブランチを利用します。

masterブランチ
リリースしたソースコードを管理するためのブランチです。このブランチで直接作業することはありません。
developブランチ
開発の軸になるブランチです。featureブランチなど他のブランチで行った作業をマージします。
featureブランチ
分岐元: develop
マージ先: develop
新機能の追加や改修などを行うブランチです。タスクごとにfeatureブランチを作成し、作業を行います。
masterやdevelopのように永続して存在せず、使い終わったfeatureブランチは削除されます。
releaseブランチ
分岐元: develop
マージ先: develop と master
リリースの準備を行うためのブランチです。リリース準備完了後にmasterとdevelopにマージされ、削除されます。
hotfixブランチ
分岐元: master
マージ先: develop と master
バグの修正など緊急対応を行うためのブランチです。このブランチでの作業内容はmasterブランチへマージされ、削除されます。

masterとdevelopは永続的に存在するブランチで、直接作業することはありません。
それぞれ必要に応じてfeature、release、hotfixブランチを作成し、作業終了後にmasterやdevelopにマージすることになります。

ワーキングフォルダAの作成

共有用のフォルダと、開発者が2人いる前提でワーキングフォルダを2つ作ります。
Windows環境の場合は部分的にTortoiseGitでもできる箇所がありますが、ここではシェル(Windows環境ではGit Bash)を使ったコマンドで説明します。

プロジェクト用のフォルダを testA という名前で作成し、作成したフォルダに移動します。Windows環境であればGit Bashを起動してください。作業したいディレクトリで右クリックして、Git Bash Here を選択するとそのディレクトリがカレント状態で開かれます。

mkdir testA
cd testA

testA にてリポジトリを初期化します。
Gitの通常の初期化は git init ですが、git-flow を使う場合は git flow init になります。
-d オプションで推奨のブランチ名が自動でつけられます。

git flow init -d

Initialized empty Git repository in C:/Users/UserName/testA/.git/
Using default branch names.
No branches exist yet. Base branches must be created now.
Branch name for production releases: [master]
Branch name for "next release" development: [develop]

How to name your supporting branch prefixes?
Feature branches? [feature/]
Bugfix branches? [bugfix/]
Release branches? [release/]
Hotfix branches? [hotfix/]
Support branches? [support/]
Version tag prefix? []
Hooks and filters directory? [C:/Users/UserName/testA/.git/hooks]

git branch でブランチの情報を確認すると、masterとdevelopブランチが作成され、developブランチがカレントになっていることがわかります。

git branch
* develop
 master

これでワーキングフォルダが1つ用意できました。
次に共有リポジトリを作成します。

共有リポジトリの作成

先ほど作成したワーキングフォルダの共有リポジトリを作成します。
testAフォルダから上の階層に移動してください。

cd ..

git clone コマンドを使って、test.gitというフォルダ名で共有リポジトリを作成します。

git clone --bare --shared testA test.git
git cloneのオプション
--bareオプション:
作業フォルダを持たないリポジトリ
--sharedオプション:
リポジトリに書き込みパーミッションを追加

ワーキングフォルダAのプッシュ先リポジトリを設定

git remoteコマンドを使って、デフォルトのプッシュ先を先ほど作成した共有リポジトリに設定します。
まずはtestAフォルダに移動し、git remote addコマンドを実行します。

cd testA
git remote add origin ../test.git

新規開発・改修用ブランチ作業

ブランチの作成

新しい機能の追加など、新規開発や改修などはfeatureブランチを作成して作業します。
まずはワーキングフォルダにて、開発用のブランチを作成しましょう。

git flow ... start の書式
git flow ブランチの種類 start ブランチ名

ブランチの種類には、新規開発・改修用であればfeature、ブランチ名には任意の名前を設定します。
ここではブランチ名にver1.0を指定します。

git flow feature start ver1.0
Switched to a new branch 'feature/ver1.0'

Summary of actions:
- A new branch 'feature/ver1.0' was created, based on 'develop'
- You are now on branch 'feature/ver1.0'

Now, start committing on your feature. When done, use:

     git flow feature finish ver1.0

ブランチの種類に feature を指定すると、developブランチから新しいブランチが作成されます。

git branch -vvで確認すると、ブランチの種類と指定したブランチ名で新しいブランチ feature/ver1.0 が作成されています。
ここではバージョン番号としましたが、開発の名称などをつけても問題ありません。

git branch -vv
  develop        ffa42c6 Initial commit
* feature/ver1.0 ffa42c6 Initial commit
  master         ffa42c6 Initial commit

下記は例ですが、何か作業したあとにコミットしてください。

vi index.txt
git add index.txt
git commit -am "1回目の編集"

featureブランチでの作業が完了したら、ブランチを終了させます。

git flow feature finish ver1.0
Switched to branch 'develop'
Updating ffa42c6 ..be92844 
Fast-forward
 index.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 index.txt
Deleted branch feature/ver1.0 (was be92844 ).

Summary of actions:
- The feature branch 'feature/ver1.0' was merged into 'develop'
- Feature branch 'feature/ver1.0' has been locally deleted
- You are now on branch 'develop'

feature/ver1.0ブランチはdevelopブランチにマージされたうえで削除されます。
git branch -vvを実行すると、developとmasterブランチのみが残り、developにfeature/ver1.0の最新コミットが反映されているのが確認できます。

git branch -vv
* develop be92844 1回目の編集
  master  ffa42c6 Initial commit

問題なければ、ローカルのdevelopブランチを共有リポジトリのdevelopブランチにプッシュします。

git push origin develop
Total 0 (delta 0), reused 0 (delta 0)
To ../test.git
   ffa42c6 ..be92844 develop -> develop

作業中のコミットやプッシュ、プル等は TortoiseGit で行うこともできます。

ブランチ終了時のエラー

コミットせずにブランチを終了しようとすると下記のようにエラーとなります。
その場合はコミットしてからブランチを終了しなおしてください。

git flow feature finish ver1.1
Fatal: Working tree contains unstaged changes. Aborting.

2つ目のワーキングフォルダを作成

複数のユーザでプロジェクトを進めるテストをしたいので、2つ目のワーキングフォルダを用意しましょう。

cd ..
git clone test.git testB
cd testB
git flow init -d

git branchを実行すると次のようにdevelopとmasterが作成されているはずです。

git branch -vv
* develop be92844 [origin/develop] 1回目の編集
  master  ffa42c6 [origin/master] Initial commit

ブランチの共有

testBで開発用の新しいブランチを作成します。

git flow feature start ver1.1

下記は例ですが、開発が完了したらコミットします。

vi index.txt
git commit -am "2回目の編集"
git branch -vv
  develop        be92844 [origin/develop] 1回目の編集
* feature/ver1.1 93fc13c 2回目の編集
  master         ffa42c6 [origin/master] Initial commit

git flow ... publishで作成したブランチを共有します。

git flow feature publish ver1.1
Counting objects: 3, done.
Writing objects: 100% (3/3), 258 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To C:/Users/UserName/test.git
 * [new branch]      feature/ver1.1 -> feature/ver1.1
Branch feature/ver1.1 set up to track remote branch feature/ver1.1 from origin.
Already on 'feature/ver1.1'
Your branch is up-to-date with 'origin/feature/ver1.1'.

Summary of actions:
- The remote branch 'feature/ver1.1' was created or updated
- The local branch 'feature/ver1.1' was configured to track the remote branch
- You are now on branch 'feature/ver1.1'

これで共有リポジトリにfeatureリポジトリが登録されました。
次にtestBで作業した内容を、testAに反映します。

cd ../testA

共有されているブランチを取得するにはgit flow ... trackを使います。

git flow feature track ver1.1
Branch feature/ver1.1 set up to track remote branch feature/ver1.1 from origin.
Switched to a new branch 'feature/ver1.1'

Summary of actions:
- A new remote tracking branch 'feature/ver1.1' was created
- You are now on branch 'feature/ver1.1'
git branch -vv
  develop        be92844 1回目の編集
* feature/ver1.1 93fc13c [origin/feature/ver1.1] 2回目の編集
  master         ffa42c6 Initial commit

feature/ver1.1ブランチがtestAに反映されました。publishとtrackはブランチ作成後1回だけ行います。
publishの後に現在のブランチで更新を行い、それを共有リポジトリに登録したくなったら通常のgit pushとgit pull、プルリクエスト等を使って更新します。

ブランチの終了

featureブランチでの作業が完了したら、ブランチを終了させます。

git flow feature finish ver1.1
git branch -vv
* develop 93fc13c 2回目の編集
  master  ffa42c6 Initial commit

最後にdevelopブランチを共有リポジトリに反映します。

git push origin develop

次にtestBに移動してブランチの情報を表示してみましょう。

cd ../testB

testAでは feature finish によりfeature/ver1.1はdevelopにマージされて、削除されています。
testBではその反映がされていないため、共有リポジトリdevelopの内容を2つ目のワーキングフォルダに反映します。

git checkout develop
git pull origin develop
git branch -vv
* develop        93fc13c [origin/develop] 2回目の編集
  feature/ver1.1 93fc13c [origin/feature/ver1.1] 2回目の編集
  master         ffa42c6 [origin/master] Initial commit

不要になったfeature/ver1.1ブランチは削除します。

git branch -d feature/ver1.1

リリース用ブランチ作業

リリース前の作業はreleaseブランチを作成して行います。
start、finish、publish、trackの使い方はは同じで、ブランチ名の部分だけ変更して使います。

リリースブランチを開始
git flow release start ver1.1
リリースブランチを共有
git flow release publish ver1.1
リリースブランチを追跡
git flow release track ver1.1
リリースブランチを終了
git flow release finish ver1.1

リリースブランチの終了手順

ブランチの開始や共有などはfeatureブランチの際と同じですが、終了は多少違いがあります。
featureはdevelopにマージされますが、releaseはdevelopとmasterにマージされ、masterにはタグの設定もあります。

まずはリリースブランチを終了します。

git flow release finish ver1.1
マージ用コメント

git flow release finish ...の後は次のようにコミットメッセージの入力画面が表示されるので、必要であればメッセージを追記します。

Merge branch 'release/ver1.2'

# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
リリースタグ用コメント

コミットメッセージを保存したあと、次にタグ名の入力をします。

#
# Write a message for tag:
#   ver1.2
# Lines starting with '#' will be ignored.

Merge tag 'ver1.2' into develop

再度コミットメッセージの入力画面が表示されますが、変更がなければこのまま保存します。

Merge tag 'ver1.2' into develop

*****

# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.

releaseブランチでの作業が完了したら、ローカルのdevelopブランチ、masterブランチをpushします。

git push --all

リリース後のバグ修正

リリース後のバグ修正作業はhotfixブランチを作成して行います。
start、finish、publish、trackの使い方は同じで、ブランチ名の部分だけ変更して使います。
リリース時にタグ名が登録されているので、今まで使っていたタグ名は使えません。現在のタグ名がver1.2であればver1.2.1など名前を変更して指定してください。

バグ修正ブランチを開始
git flow hotfix start ver1.2.1
バグ修正ブランチを共有
git flow hotfix publish ver1.2.1
バグ修正ブランチを追跡
git flow hotfix track ver1.2.1
バグ修正ブランチを終了
git flow hotfix finish ver1.2.1

バグ修正ブランチの作成手順

startコマンドでブランチを作成する際、featureブランチとreleaseブランチはdevelopブランチから作成されますが、hotfixブランチはmasterブランチから作成されます。

git flow hotfix start ver1.2.1

バグ修正ブランチの終了手順

ブランチの開始や共有などはfeatureブランチの際と同じですが、終了は多少違いがあります。
hotfixはdevelopとmasterにマージされます。

修正作業とコミットが終了したら、バグ終了ブランチを終了します。

git flow hotfix finish ver1.2.1
マージ用コメント

git flow release finish ...の後は次のようにコミットメッセージの入力画面が表示されるので、必要であればメッセージを追記します。

Merge branch 'hotfix/ver1.2.1'

# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
バグ修正タグ用コメント

コミットメッセージを保存したあと、次にタグ名の入力をします。

#
# Write a message for tag:
#   ver1.2
# Lines starting with '#' will be ignored.

Merge tag 'ver1.2' into develop

再度コミットメッセージの入力画面が表示されますが、変更がなければこのまま保存します。

Merge tag 'ver1.2.1' into develop

*****

# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.

releaseブランチでの作業が完了したら、ローカルのdevelopブランチ、masterブランチをpushします。

git push --all

関連記事