Gitのブランチを頑張って解説する

構成管理のツールにはかかせないブランチという機能。Gitのブランチってどんな仕組みなの？というところを書いていきます。

## ブランチ is 何？
まずは構成管理ツールにおける、ブランチってなんなの？というところから。
ブランチを一言で表すと、
<b>ほかの人の開発の邪魔をせず、自由に開発するための機能</b>
って感じです。<span style="font-size: 80%">一言でって難しいよね。。。</span>

### というわけで例え話
自動車を生産する工場をイメージしてください。
<b>ブランチなしで自動車工場</b>
一か所の作業場で、板金、組み立て、塗装などすべての作業をしようとしているようなイメージです。
エンジンもタイヤもシートもすべてその場で作っている状態です。わちゃわちゃしてそうでしょ。
シートの革を一枚一枚丁寧に縫製している横から、塗装のスプレーの流れ弾が飛んできて、革の質感が台無しに、、なんて悲劇が起こるかもしれません。

<b>ブランチありで自動車工場</b>
パーツ、工程ごとに専用の工場があるイメージです。
エンジンはエンジン工場、タイヤはタイヤ工場、シートはシート工場で作成され、完成されたものがメインの生産工場に納入されて、自動車に組み込まれます。
この方法なら、シートの縫製中に汚される心配もありませんね。

ちょっと誇張しましたが、ブランチというのは生産ラインを分けるというイメージと捉えられるかなと思います。
システム開発の構成管理においても、ほかの人の開発を邪魔せず(ほかの人の開発に邪魔されず)開発を進めていくための作業場の役割を果たすのがブランチです。

## Gitにおけるブランチとは？
ブランチを理解するうえで、ちゃんと解いておきたいありがちな勘違いを紹介します。
(自分が勘違いしていただけで、本当にありがちな勘違いなのかどうかは知らないです。。)

その勘違いとは、ブランチを「線」だと解釈することです。

![Gitブランチ001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/733043/ca7f9c90-4a98-e719-ada0-9b18d2f85c5d.png)

hogeとfugaの二つのブランチを使って説明します。(ここでのブランチ名に特に意味はありません。)
ソースの修正を確定させて、Gitに登録する操作をコミットといいます。この図では黒い四角の箱でそれを表現しており、中にはコミットを行った際に記録される情報の一部を記載しました。(中身はテキトーです。)

勘違いパターンとは、このコミット同士をつなぐ線のことをブランチと思ってしまうことです。
しっくりきやすいのでこう覚えてしまいがちですが、Gitにおけるブランチというのは、線ではないのです。


これが正解。

![Gitブランチ002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/733043/62188e6d-136e-8553-1c3a-27de319f073d.png)

いうならば「線」ではなく、「点」と表現できます。
Gitのブランチとは、<b>特定のコミットへのポインタ</b>なのです。
コミットというのは、その時のソースの状態のスナップショットを保持してくれるものなのですが、開発を進めていくとそれは無数に増えていくものです。
(ちなみに自分が仕事をしているプロジェクトでは、5万弱のコミットが行われています。)
それをうまく管理して、扱いやすくするためにブランチというものが存在するのです。要するに<b>目印</b>になるんですね。

じゃあ、勘違いパターンだった「線」って、ブランチじゃなかったらなんなの？という疑問が出てきますね。
これは<b>コミットの親子関係</b>を表します。
上の図のコミットの情報で、「Parent aaaaaaa」と記載されているのは、そのコミットの親コミットを記録しているのです。
コミットをしたときに、その直前に行われていたコミット(HEADというポインタが指しています)を親コミットとして記録することで、コミット同士の線のつながり＝親子関係ができあがるのです。
また、二つのコミットを親とするコミットを作ることができます。これをマージコミットといいます。

つらつらと書きましたが、一番覚えておきたいのは<b>「ブランチはコミットの目印」</b>ということです。
Git操作によってこの目印の位置を自由に操作できるようになると、Git便利だなぁ～って感じられるようになると思います。

## Gitコマンドでブランチを操作する
ブランチは目印であるということを意識して、いくつか代表的なブランチの操作を紹介します。

### ブランチを作成する

```
git branch <ブランチ名>
```

新しい目印を作ります。
自分が作業をしているブランチの目印の位置で作成してくれますが、ブランチ名の後ろに既存の別のブランチ名を指定すると、指定したブランチのコミット位置で新しいブランチを作成できます。

### 作業するブランチを変更する

```
git checkout <ブランチ名>
```

一つのローカルリポジトリの中で、同時に作業に使えるブランチは一つだけです。
このcheckoutコマンドを使って、ブランチを切り替えながら作業していくことになります。

ちなみに、ブランチを作成する⇒作業するブランチを変更する　をコマンド一発で行うことができます。

```
git checkout -b <ブランチ名>
```

このコマンドでも、作成元のブランチの指定が可能です。

### 扱っているブランチの一覧

```
git branch -a
```

今作業しているブランチ、ローカルブランチの一覧、リモート追跡ブランチの一覧が確認できます。
ブランチの確認はこのコマンドだけ覚えていれば、困ることは何もないかと。

※完全に備忘用：リモートリポジトリに上がっているブランチをすべて表示するコマンド

```
git remote show <リモート名>
```

### ブランチを削除する

```
git branch -d <ブランチ名>
```

強制的に削除する場合

```
git branch -D <ブランチ名>
```

リモート追跡ブランチを削除する場合

```
git branch -dr <リモート追跡ブランチ名>
```

リモートブランチを削除する場合

```
git push <リモート名> :<ブランチ名>
```

リモート追跡ブランチの削除の場合は、-rオプションを追加します。
リモートブランチの場合、通信が必要なので、pushコマンドに用意されたオプションを使います。
目印を一つ消すだけなので、怖がる必要はそんなにないコマンドだと思っています。

### ブランチ名を変更する

```
git branch -m <旧ブランチ名> <新ブランチ名>
```


### 別のブランチのコミットを作業中のブランチに取り込む

```
git merge <取り込むブランチ名>
```

本題ではないので紹介だけ。
二つの親コミットを持つマージコミットの作り方です。

### 目印の位置を任意の場所に変更する

```
git reset <コミット>
```

軽率に紹介してみましたが、「resetって何？」って思った方は<b>使用を控えることを全力でオススメします！</b>
やらかすと開発現場を数時間ストップさせるくらいの魔力を持っています。ご利用は計画的に。

※ちなみに、GitHubを使っている場合は、ブラウザから簡単にリモート上でのブランチ作成、削除等が可能です。他のGUIでもあるんだろうけど。。

## Gitのブランチの使い方のベストプラクティス
最後に、Gitの便利なブランチという機能をより効率的に使いこなしていくためのベストプラクティスとして、<b>「git-flow」</B>と<b>「GitHub Flow」</b>という二つのワークフローを簡単に紹介します。
このワークフローってどういうものかというと、ブランチを役割ごとに分類して、運用ルールを定めて、効率よくシステム開発を進めよう！というものです。

### git-flow
git-flowは比較的大規模な開発向けの、複雑で厳密なワークフローです。

![git-flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/733043/4ea3ce82-bbea-e7fb-5ddf-ed7e0311136e.png)

ブランチの役割とルールを簡単に。

|ブランチ|役割|
|:--|:--|
|master|リリースされた、出来上がったソースが保管される。リリースのたびにバージョン番号をつけてタグを打つ。|
|develop|開発の中心となるブランチ。出来上がったソースをこのブランチに集めていくことになる。このブランチのソースが最新。|
|feature branches|開発のタスクに応じて切られる。このブランチを使用して開発し、作業が完了したらdevelopにソースをマージする。|
|release branches|リリースをする際にdevelopから分岐する。バグ修正など、どうしても必要な更新以外は行わない。<br>リリースが完了したら、masterとdevelopにそれぞれマージを行う。|
|hotfixes|緊急でパッチを当てる必要がある場合などに、masterから直接分岐させる。作業完了後には、masterとdevelop(またはrelease)にそれぞれマージを行う。|


正直、小さいチームであればやりすぎ感のあるワークフローです。理にかなっているのは確かだと思うのですが。。
個人的にオススメは、次のGitHub Flowです。

### GitHub Flow
GitHubの機能を活用したワークフローです。
主にプルリクエストの機能を活用しながら、ブランチ構成はシンプルに、いくつかのルールをみんなで守っていく、というスタイルです。

![GitHub_Flow_steps.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/733043/1021fe77-fc4b-7c1a-e5eb-d1543538de7b.png)


|ブランチ|役割|
|:--|:--|
|master|開発の中心となるブランチ。常にデプロイが可能な状態をキープする必要がある。|
|topic|開発を行うブランチ。そのブランチで行う作業内容をそのままブランチ名にする。|

ブランチの分類は二つだけでとても理解しやすいです。
ほかにもいくつかルールがあります。
・小さな作業単位でこまめにコミットする。
・ブランチでの開発が済んだら、masterへのプルリクエストを作成し、ソースレビューを受ける。
・レビューでOKが出たら、速やかにマージを行い、デプロイする。

重要なのはmasterはいかなる時もデプロイが可能であるということです。
この前提を崩さないために、しっかりとレビューをして、デプロイを阻害するソースをmasterにマージすることを防ぐ必要があります。
これが守られることにより、高頻度でのデプロイが可能な状態をキープできるわけです。

やっぱりレビューは大切ですね。
プルリクエストという機能も、レビューをするためのものとしてとても進化しており、手軽で使いやすいサービスになっています。

<hr>

ブランチについて長々と説明してきました。簡潔にまとめるスキルが欲しい。。。
最後にもう一度言いますが、<b>ブランチを使いこなせると、本当にGit便利だな～ってなる</b>と思うので、それが感じられるようにいろいろ使って試してみてください！