シロク流、Gitの使い方


# 0. Gitを使ったことがない方へ
Gitの基礎は下記の通りです。
## 「みんなの作業場」と「自分の作業場」
- ワーキングツリー

　　↓ add

- インデックス（ステージ）

　　↓ commit

- ローカルリポジトリ

　　↓ push

- リモートリポジトリ

リモートリポジトリが「みんなの作業場」で、上3つが「自分の作業場」です。
基本的に、「自分の作業場」でのみファイルの変更をし、変更内容を「みんなの作業場」に投げ込むイメージ。

- 「commit」は、作業履歴を保存すること。
- 「add」は、commitするファイルを予め選択するためのコマンド。言わば、commitの前段。commitの準備。
- 「push」は、自分の作業場の履歴（commitのログ）を「みんなの作業場（リモートリポジトリ）」に反映させること。

コマンドの叩き方の例は下記の通りです。

```
git add ファイル名
git commit -m "コミットメッセージをここに書く"
git push origin develop
```

# 1. ブランチの命名と意味
シロクでは、

- masterブランチ：prd環境に相当。
- developブランチ：stg環境に相当。
- feature/xxxブランチ：機能ごとにブランチを切る。

というブランチの切り方をしています。

（参考）
シロクのGitルールは、基本的に「A successful Git branching model」という手法を踏襲しています。
参考サイト：http://nvie.com/posts/a-successful-git-branching-model/
日本語訳：http://keijinsonyaban.blogspot.jp/2010/10/successful-git-branching-model.html
## 1-1. masterブランチ
- masterブランチ上でcommitすることは絶対にしません。
- 必ずdevelopブランチからのマージにより、更新させる。

## 1-2. developブランチ
- リリース前のプロダクトに限り、developブランチで作業を進める。
- リリース後のプロダクトは、developブランチ上でcommitしてはいけません。
- リリース後であれば、必ずfeature/xxxブランチに移動してから作業を進めること。

## 1-3. feature/xxxブランチ
- 機能ごとにfeature/xxxブランチを切り、ブランチ上で作業をします。

# 2. `git rebase`と`git merge`のルール
## 2-1. ブランチは基本1本線
シロクでは、基本的にブランチの枝分かれは「機能ごと」でのみ分けるものとし、「人ごと」にブランチを切ることはしません。

その時、重宝するコマンドが、`git rebase`です。
例えば、

```
git rebase origin/develop
```

と叩けば、「今いるブランチをdevelopブランチの進捗に合わせる」ことができます。
これをすることで、複数人で同じブランチで作業していても、基本的に1本線で作業を続けることが出来ます。

#### (注1) git rebaseをするタイミング
いつも通り、「add　→　commit　→　push」をしてうまくpushすることができれば、rebaseの必要はありません。

同じブランチ上で自分以外の誰かがpushしていた場合、pushしようとすると失敗する。
この時、`rebase`してから`push`することになります。
`rebase`する前には必ず`fetch`をし、リモートの更新履歴を取得する必要があります。
（fetchコマンドではmergeはされません）

```
git fetch origin
git rebase origin/develop
```

#### (注2) git rebaseが失敗する時もある
自分以外の人がpushした内容と、自分の変更内容が同一箇所である場合、rebaseが失敗することがあります。

そんな時は下記ブログがとても参考になります。

▼git rebase 失敗した時の対処法
http://qiita.com/shuntaro_tamura/items/c505b76c1021a35ca9ff

## 2-2. ブランチをマージする時は、別ブランチからのマージであることを必ず残す
シロクでは、ブランチのマージをする際、fast-forwardな関係にあるコミットを統合する場合においても必ず枝分かれさせてマージします。

機能ごとの各ブランチにおいては枝分かれはさせず1本線にするが、そのブランチをマージする際には必ず「--no-ff」オプションをつけ、枝分かれを残すようにしています。

例えば、feature/xxxブランチをdevelopブランチにマージしたければ、

```
git checkout develop
git merge --no-ff feature/xxx
```

とたたきます。
（マージ先に移動してから、mergeコマンドをたたく）

また、リリースする時はマージコミットのメッセージをバージョン番号にするというルールにしているため、

```
git checkout master
git merge --no-ff develop -m "1.0.1"
```

のようにたたきます。

## 2-3. シロクのGitルール
- 絶対にmasterブランチでは作業しない（リリース前はdevelop、リリース後はfeatureブランチ）
- 基本1本線（rebase）
- ブランチのマージは`--no-ff`オプションつける
- こまめにコミット（コンフリクトを避ける）
- SourceTreeを入れる（基本CLIでたたくが、枝葉を見るために使用）
- 悲劇を起こさないために：commit前に必ず「git status＆git diff --staged」をチェックする
  - 身に覚えのないコミットあり：「git submodule update --init --recursive」

## 2-4. その他便利なGitコマンド
#### ①ブランチの「閲覧、作成、削除」
```
git branch
git branch ブランチ名
git branch -d ブランチ名
```

- 上から順に、「閲覧、作成、削除」
- `branch -d`：消したいブランチ上にいたら消せない。移動してから消す。

#### ②ブランチの「移動、作成＆移動」
```
git checkout ブランチ名
git checkout -b ブランチ名
```

- `-b`オプションを付けることでブランチの作成と移動を同時に出来る。

#### ③インデックスに追加（add）
```
git add ファイル名
git add .
git add -A
```

- `git add ファイル名`：指定したファイルをadd
- `git add .`：新規作成/変更されたファイルを全て追加。削除は対象外。
- `git add -A`：新規作成/変更/削除されたファイル全てを追加。(AllのA)

#### ④ローカルリポジトリに変更履歴を保存（commit）
```
git commit -m "コミットメッセージをここに書く"
git commit -am "コミットメッセージをここに書く"
```

- `git commit -m "message"`：addしたものをコミットメセージとともにcommit
- `git commit -am "message"`：変更加えたファイルを自動検出してcommit
  - 便利だが、思わぬ事故を招きかねないので個人的にはあまり使わない

#### ⑤インデックス追加後のおまじない
```
git status
git diff --staged
```

- `git status`：ワーキングツリーのファイルとインデックスに追加されたファイルをチェック
- `git diff --staged`：ファイルの変更差分をチェック

#### ⑥コミットの取り消し、打ち消し、上書き
```
git reset --hard HEAD^
git revert コミットのハッシュ値
git commit --amend
```

- ブログ参照：http://qiita.com/shuntaro_tamura/items/06281261d893acf049ed

#### ⑦ファイルの変更履歴を行単位で調べる方法
```
git blame ファイル名
git show コミットのハッシュ値
```

- ブログ参照：http://qiita.com/shuntaro_tamura/items/b8b99a9b4987144581e9

#### ⑧やり直したい時に便利「git reset」とそのオプションを使いこなす
```
git reset --hard HEAD^
git reset --soft HEAD^
```

- ブログ参照：http://qiita.com/shuntaro_tamura/items/db1aef9cf9d78db50ffe

#### ⑨変更内容の一時退避
```
git stash
git stash pop
```

- `git stash`：変更内容を一時退避
- `git stash pop`：退避させた内容を元に戻す