俺俺github-flow

## 概要

公式のgithub-flowをベースに、入門用として簡易化したgithub-flowとチケット管理システムとの論理的な連携について説明する。

## 前置き

- [gitの操作方法](http://www.backlog.jp/git-guide/intro/intro1_1.html)
- [本来のgithub flowの概念](http://b.pyar.bz/blog/2014/01/22/github-flow/)
- チケット管理システムとtaskboard(KANBAN)の理解

### なぜ素のgitを使わないのか

- 開発安定版ブランチ（以下develop）へのマージに対する心理障壁を低くしたい
- 簡単に(1)コードレビューして、(2)マージという流れで操作したい
- リモートのdevelopブランチへpushしなければならないルールから抜けたい

### 想定する環境

- macかlinuxのコンソール
- github

### ここで出てくるコマンドと用途

- `git clone URL`
	- リモートからローカルへソースツリーをコピー
- `git checkout -b BRANCH`
	- 新しいブランチを現在ブランチから作成（枝分かれするぞ）
- `git checkout BRANCH`
	- 既存のブランチへワークスペースを移動
- `git add .`
	- ブランチへの変更を追加する
- `git commit -m 'COMMENT'`
	- ブランチへの変更を確定する
- `git commit --amend -m 'COMMENT'`
	- 最新のコミットメッセージを書き換える
- `git log --oneline`
	- コミットコメントとリビジョン番号だけ表示する
- `git push origin BRANCH_NAME`
	- BRANCH_NAMEに相当するブランチをリモート(origin)にコピー
- `git pull origin develop`
	- リモート(origin)のdevelopブランチから現在のブランチへマージ
- `git rebase -i BRANCH_NAME`
	- 現在のブランチのHEADからBRANCH_NAMEに相当するブランチのHEADまでのcommitをマージする
- `git fetch --prune`
	- 無効になったリモートリポジトリの情報を管理情報から削除する
- `git branch -d BRANCH_NAME`
	- ローカルブランチを削除する

## 1. 大まかな事前準備

1. githubでrepositoryを作成する
2. ローカルにcloneする
3. ブランチがmasterになっているので、developへ切り替えてfirst commit.
4. リモートにdevelopをpushする
5. githubのsettingsを開き、デフォルトブランチをdevelopに設定
6. TOPページに戻って上部メニューのbranchを辿るとmaster , developの２つが見える
7. おもむろにmasterブランチを削除。以降masterはdevelopからtagを使って切り出すだけの存在へ。
8. .git/hooks/prepare-commit-msgを配置する。
9. 試しに別のリポジトリをローカルで作成して`prepare-commit-msg`の効果を確かめてみろ
9. 準備は整った！

```
$ git clone https://github.com/hogehog.git # 2
$ cd hogehoge/
$ git checkout -b develop # 3
$ echo 'hogehoge poo' > README.md # 3
$ git add . # 3
$ git commit -m 'first commit' # 3
$ git push origin develop # 4
$ touch .git/hooks/prepare-commit-msg # 8
$ vi .git/hooks/prepare-commit-msg # 8
```

```.git/hooks/prepare-commit-msg
#!/bin/sh

# BRANCH_NAME COMMIT_MESSAGES

# ブランチ名取得
branch=$(git branch | grep ^* | sed 's/\* //g')

# first commit前等で、ブランチ名が取れなかった時用
if [ ! $branch ]; then
 echo 'branch name CAN NOT retrieved..'
 exit 1
fi

if [ $branch == 'develop' ]; then
 echo 'DO NOT COMMIT to $branch !!!!!!!'
 exit 1
fi

if [ $branch == 'master' ]; then
 echo 'DO NOT COMMIT to $branch !!!!!!!'
 exit 1
fi

# コミットメッセージの置換
msg=$(cat $1 | sed -e "s/ (branch:[0-9a-zA-Z_]\+)$//g")
if [ $branch != 'master' ]; then
  msg="$branch $msg"
fi
echo $msg > $1
```

## 2. 大まかなフローはこのとおりだ

1. リモートのdevelopから最新を取得する
2. チケット番号単位でタスクブランチを作成する
3. タスクブランチにcommitし、リモートもタスクブランチのままpush
4. githubでcompareしてコードレビュー
5. 他者にマージ実行してもらう

### 良い所

- 人間がpushするのは必ずdevelop以外になること
	- 危うくdevelopにpushしてしまいそうなら、github側でprotected branchに登録するんだ。
	- addしてしまっていたらstashすればいい。その後は自分で調べるんだ。
- developにマージするのはgithubだけということ
- そして何より、マージする前にコードレビューを挟み込めること
	- ここで色々なWeb的な連携が可能になるのもミソだ
	- CIで全テストをやってもらってもいい

### 悪い所

- チケット番号単位でブランチを作成するからその分コードレビューもチケット番号単位になるんだ
- 細かくチケットを分割し過ぎると作業量もその分増える
- チケットを細かくしてもそれらを統括するようなチケットを用意して、その番号でレビューをしてもらえば回避できる
- これは都合の良い方法を自分で探すんだ

## 3. さあ始めよう俺俺github-flow

1. taskboard(KANBAN)からチケット番号を見つけよう。ここでは100番だ。
2. まずはリモートからdevelopをpullしてローカルを最新にしよう。
3. そして、ブランチ名OREORE_100をdevelopから作成する（チケット番号の前には何かの略語を入れると様になるぞ）
4. ロジックを書いて〜
5. OREORE_100へcommit
6. そのままOREORE_100をリモートにpush
7. githubを見て、developとOREORE_100をcompare & pull requestする（緑色のボタンをクリックだ）
8. pull request作成画面に移動するのでタイトルと修正内容をコメント欄に書き、 create pull requestだ。
	- コメント欄にはチケットのURLを書いておくといいぞ
	- チケット側にはpull requestのURLを書いておくといいぞ
9. 誰か他の人にこのpull requestをコードレビューしてもらえ 
	- このブランチが開発安定版developにマージされていいかの視点を持って確認する作業だ。
	- タスクと関係ないファイルの変更がコミットに余分に含まれていることがある。そういうのも指摘するんだ。
10. 問題なければ`This pull request can be automatically merged.`と出ているはずだ。
	- 問題があれば`conflictを解消しろ`と出ているはずだ。
	- 問題がなければ、誰か他の人にmerge pull requestをクリックしてもらえ（緑色のボタンをクリックだ）
11. 更に confirm merge をクリックしてもらえ
12. メッセージの左のアイコンが紫色になったら Merged でdevelopへOREORE_100がマージされた！
13. もうOREORE_100は不要だったら、ついでに同じ画面から Delete branchだ。
14. ローカルのブランチをdevelopに戻そう
15. ローカルのdevelopも最新化しておけ
16. ついでにgithubで削除したブランチの接続情報を掃除しておけ
17. ついでに無用になったローカルブランチも掃除してしまえ

```
$ git pull origin develop # 2
$ git checkout -b OREORE_100 #3
$ git add . # 5
$ git commit -m 'implemented oreore methods.' # 5
$ git push origin OREORE_100 # 6

$ git checkout develop # 14
$ git pull origin develop # 15
$ git branch -a # 16
$ git fetch --prune # 16
$ git branch -d OREORE_100 OREORE_101 master # 17
```

```
### git fetch --prune 例

(before)

$ git branch -a
  OREORE_100
  OREORE_101
* develop
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/OREORE_100
  remotes/origin/develop
  remotes/origin/master

$ git fetch --prune


(after)

$ git branch -a
  OREORE_100
  OREORE_101
* develop
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/develop
```

## 4. commitのたびにpushしなくてもいいぞ？rebase -i developだ

1. 前述の操作同様に、developからOREORE_101を作成する
2. OREORE_101ブランチで何度かcommitをする
3. logを確認すると自分のコミット履歴が見えるぞ
4. このままdevelopへのマージ操作に入ってもいいが、煩雑な履歴になるからrebaseして綺麗にしよう
5. 先頭だけ残して残りはpickからfixupに書き換えて保存しろ
6. 他のコミットが最初のコミットにまとめられた。リビジョン番号は変化するぞ。
7. コミットコメントが内容に沿わなくなったから書き換えろ
8. 終わったらremoteにpushしてpull requestだ！

下の方に補足で書いている例を確認すると気づくことがあるだろう？commit前、rebase前、rebase後を比較すると`rebase -i develop`が何をしたか理解できるはずだ。

理解できない人のために説明すると、commitで増えたHEADからdevelopの最新HEADまでの間をインタラクティブにマージしたんだ。リビジョン番号を指定して部分的にマージしてもいいが、自身の細々としたログだけ片付けられればいいのでdevelopの最新HEADとの差分全てをマージしてしまえばいい。

```
$ git checkout -b OREORE_101 # 1
$ git add .
$ git commit -m 'implemented create method' # 2
$ git add .
$ git commit -m 'implemented update method' # 2
$ git add .
$ git commit -m 'implemented delete method' # 2
$ git log --oneline
$ git rebase -i develop # 4
$ git log --oneline
$ git commit --amend -m 'implemented CRUD method' # 7

$ git push origin OREORE_101
```

### commit 前

```
$ git log --oneline
cdfd5ec Merge pull request #1 from imasami/OREORE_100
3699a52 OREORE_100 oreore
c5e7e60 Initial commit
```

### rebase 前

```
$ git log --oneline
2c7900e OREORE_101 implemented create method
c6db866 OREORE_101 implemented update method
15d024b OREORE_101 implemented delete method
cdfd5ec Merge pull request #1 from imasami/OREORE_100
3699a52 OREORE_100 oreore
c5e7e60 Initial commit
```

### rebase 後

```
$ git log --oneline
933ba0d OREORE_101 implemented CRUD method
cdfd5ec Merge pull request #1 from imasami/OREORE_100
3699a52 OREORE_100 oreore
c5e7e60 Initial commit
```