レガシーな人のための Git入門

# 対象の読者     
- Gitについて概要を知りたい方
- Gitを用いた開発にこれから参加しようとしている方
- Web業界でよく使われるツール/方法に興味のある方
- ソフトウェア/システム開発に関わり、開発効率を上げたい方
    - 特に、Web業界以外の、歴史の長い業界でのソフトウェア開発に関わっている方

# 概要
本シリーズでは、web業界等、比較的新しいソフトウェア/システム開発でよく用いられる開発ツールをピックアップし、近年の動向にあまり詳しくない人にもわかりやすく紹介することを目的とします。

また、レガシーな手法と比べて何が良いのか、対比を踏まえて紹介し、簡単なチュートリアルも用意しています。

# 今回紹介するツール
| ツール名 |  カテゴリ |
|:-------:|:---------:
| Git | ソースコード管理 |

# 注意点
筆者は数年前までWeb系でない、レガシーな環境にいたため、
既にWeb業界にいる方には当たり前の事が書かれているかもしれません。

# Git紹介 (本編)

### ツール概要
Gitは、端的に言うと、主に下記の２つの機能を実現するソフトウェアです。
1. ソースコードのバージョン管理
2. ソースコードの並行開発管理 (レビューを含む)

---
#### 機能1.　ソースコードのバージョン管理
プログラムを書きすすめていたところ、バグを埋め込んでしまい、動かなくなってしまった経験はどなたにもあるかと思います。そのバグがない状態まで元に戻そうとした時に、うまく戻せるでしょうか？

古典的な方法では、古いバックアップファイルないしフォルダから戻すことになるでしょう。
しかし、埋め込んだバグ以外の、正常な機能も無かったことになるかもしれません。
また、戻す過程で直したバグが復活してしまうかもしれません。

Gitのバージョン管理機能では、こういった心配をほぼ無くすことができます。
誰が、いつ、何を実装したかが全てトレースできるためです。
>
![Git_legacy_2.png](https://qiita-image-store.s3.amazonaws.com/0/171284/08840589-a53d-829d-f141-63bdd200e1b9.png) 
図: Gitの履歴表示例 (IDE内蔵の機能で表示)　ツリーの任意の地点に戻すことも可能です。


>
![Git_legacy_3.png](https://qiita-image-store.s3.amazonaws.com/0/171284/c1def50a-a5b6-a2f1-6538-bcec09ec8181.png)
図: GitのDiff表示例　(IDE内蔵の機能で表示) 一つ前の世代との差分も表示できます。


##### 何がうれしいか
- 手動での、バージョン毎のフォルダ管理を無くせる。
- フォルダと違い、気軽にスナップショットを作成できるため、細かく世代管理できる。
- 作業履歴が残るため、何を誰がいつ変更したかがわかるようになる。

##### 使い方の流れ
###### ローカル開発環境
- まずリポジトリという、作業場のようなものをフォルダと紐づけて初期化します。(git init)
    - 通常、ソフトウェアとリポジトリを１対１に対応させ、さらにリポジトリとフォルダも１対１に対応させます。
- リポジトリには、変更履歴といったメタデータも含まれます。
- そこに、ソースコードを放り込み、特定のコマンド(git add)を実行し、管理対象として認識させます。
- そのソースコードを使いなれたエディタなどで変更します。
- 有る程度きりがよい所までプログラムを書いたら、特定のコマンド(git commit)で、スナップショット、変更履歴、コメントを残します。

これだけで、バージョン管理を実施することができます。
###### リモート開発環境
- Gitは更にリモート(共有サーバーに相当)環境に、上記管理情報を持たせることが出来ます。
- リモートサーバ上でリポジトリを作成し、ローカルに複製(clone)し各自が作業する、という流れが一般的です。
- ローカル環境の変更履歴をリモートサーバーに反映することを、GitではPushと言います。
- 逆に、リモートサーバーの変更履歴をローカルに反映することを、GitではPullと言います。
- Pushすることにより、実質的なバックアップがとれるだけでなく、他の人やPCに対してコードや変更履歴を共有する事ができるようになります。
- リモートサーバのホスティングサービスの例としては、[Github](https://github.com/)、[Bitbucket](https://bitbucket.org/)、[Gitlab](https://about.gitlab.com/gitlab-com/)などがあります。

##### チュートリアル
###### ローカル開発環境
- Gitをローカル環境にインストールし、管理したいソースコードがあるフォルダ配下でinit, add, commitを実行してみましょう。
    - コマンドライン派の方は、[Git公式サイト](https://git-scm.com/)からGitをダウンロードし、コマンドを打ってみましょう。
        - 使い方は、[こちらの記事](http://qiita.com/konweb/items/621722f67fdd8f86a017)が特にまとまっており参考になります。
       - 各コマンド毎の詳細は、公式ドキュメント[Git Reference](https://git-scm.com/docs)でコマンド毎に見ることができます。
    - GUI派の方には、[Sourcetree](https://www.sourcetreeapp.com/)がオススメです。
       - 使い方は、[こちらのブログ](https://nelog.jp/sourcetree-local-repository-commit)が特に丁寧かつまとまっており参考になります。
    - また、IDEを普段お使いの場合、Gitとの連携機能が内蔵されている場合があります。その場合、IDEとの連携機能が提供されている場合が多いため、それを使用するのもオススメです。
        - ただし、IDEの使い方と、Gitの使い方を同時に学習する必要があるため、まずはコマンドラインorGUIツール単体ではじめたほうがよいかもしれません。
    - どの方法でも、初めてcommitする場合、名前とメールアドレスを要求されます。ダイアログの指示に従い登録しましょう。この情報で、変更履歴に刻印されるようになります。  

###### リモート開発環境
- ローカル環境でinitする代わりに、Gitリモートサーバ([Github](https://github.com/)など)上で、リポジトリを作成してみましょう。
- そして、cloneを(ローカルから)実施し、ローカルに上記リポジトリを複製してみましょう。そして、クローンしたローカルのリポジトリに対しファイルをaddし、commitし、pushしてみましょう。
    - コマンドラインを用いる場合、[こちらの記事](http://qiita.com/nt_tn/items/c5ea999a2638e03ee418)が特に参考になります。
- Pushした結果がリモートサーバ上に反映されたか確認してみましょう。

---
#### 機能2.　ソースコードの開発管理(レビュー含む)
この機能は、主にチーム開発に役立つ機能になります。

チームで開発する場合、同じフォルダで作業をすると、同じファイルを編集するときにロックをとれず編集できない人が出てきたり、意図せず上書きしてしまうなどのトラブルが発生します。
また、他のメンバが新しいコードを追加する時に、コードレビューをし忘れないように管理する必要が生じます。

Gitの開発管理機能では、これらを簡単に実施することができます。

##### 何がうれしいか
- Gitの機能を用いて、独立した作業空間を簡単に手に入れられる。
- 作業結果の統合時に、複数人が同一ファイルを変更していても、自動的に統合されるか、競合を検知できる。
- 個々の作業結果をリモートサーバ上の共有空間に反映する際に、レビューに通す手順を仕組みで担保出来る。
  - これは正確には、Gitではなく、リモートサーバのホスティング機能です。

> 
![Git_legacy_4_0.png](https://qiita-image-store.s3.amazonaws.com/0/171284/b6ee1e6a-73f8-23ff-2de1-2228d58d91ef.png)
図: 独立した作業空間を手に入れる例。
リモートサーバ(この例ではGithub)のUIより、新しい作業空間(ブランチ)を現在のバージョンを基に作成しています。

> 
![Git_legacy_4_1.png](https://qiita-image-store.s3.amazonaws.com/0/171284/29790ee9-1cf3-da58-8352-180e2a591160.png)
図: Githubのレビュー機能の表示例。作業後、共通ブランチに作業を反映する際、承認者を決め、レビューを依頼しています。
(悲しい事にこのリポジトリは１人で作成した物なので、設定できていません。。)

> 
![Git_legacy_5_2.png](https://qiita-image-store.s3.amazonaws.com/0/171284/3c85b53c-dff9-33fe-87d8-9ede71766589.png)
図: レビュー画面では、以前のバージョンとの差分が表示され、承認者がコメントを挟むこともできます。競合がある場合、競合箇所の確認が要求され、解消するまで共通の作業空間(ブランチ)に反映できないようになります。  

>
![Git_legacy_5_1.png](https://qiita-image-store.s3.amazonaws.com/0/171284/6c298c39-1473-2c79-4154-014a254beab3.png)
図: 他の人の作業と競合がなければ、緑のMergeボタン(承認ボタン相当)を押すことで、変更を共通の作業空間(ブランチ)に反映できます。

##### 使い方の流れ
- Gitはリポジトリの中に、"ブランチ"という分岐を持たせることができます。(git branch)
    - 新しいフォルダに既存のフォルダの内容をコピーし、新しいフォルダで編集を開始するのにイメージとしては似ています。
    - これにより、チームメンバが、他の人と競合せずソースコードを編集できるようになります。
- ある程度作業したら、最終的にリモートサーバの共有ブランチ(一般的にはdevelopブランチ,masterブランチなど)に個人の作業結果を反映(merge)します。
    - リモートサーバ([Github](https://github.com/)など)にある、PullRequest, といった機能を用いるのが一般的です。
        - [こちらのサイト](https://www.backlog.jp/git-guide/pull-request/pull-request1_1.html)の説明が、とてもわかりやすいです。
    - リモートサーバが自動でテキスト解析を行い、複数人の作業を自動的に統合します。
    - 同じ機能に対して２人以上の手が入るなどで、自動的に統合出来ない場合のみ、人が介入して競合解消を実施します。
    - レビュアーがレビューおよびコメントをした後、共通ブランチへの作業反映を承認します。

##### チュートリアル
- まずはリモートリポジトリ上でリポジトリを作成した後、ローカルにcloneしてみしょう。(cloneはローカルで実施)
    - コマンドの場合、`git clone <リポジトリのURL>`で実行できます。
    - Clone後、どのようなブランチがあるかの確認は、`git branch --list`で確認できます。
- リモートサーバ上のUIで、master(初期ブランチ)から、様々な用途のブランチを作成してみましょう。
    - [git-flow](https://danielkummer.github.io/git-flow-cheatsheet/index.ja_JP.html)では、ソフトウェア開発において、どのようなブランチを切り、どう使えばよいかの方法論と、それを抽象化したコマンドラインツールを提供しています。
    - まず、masterブランチから、開発用共有ブランチ develop を 分岐させて作ってみましょう。
    - developブランチから、作成する機能毎に、機能ブランチを作成しましょう。
        - 次のように、末尾に　/担当者名 をつけると、誰が作業しているか判るようにできます。
        - 例:  feature/new_function/my_name
- これらのブランチをリモートサーバ上で作成したら、ローカルでfetchコマンドを実行し、ローカル環境に存在を反映してみましょう。
    - コマンドの場合、`git fetch`し、`git branch --list --all`で存在を確認しましょう。
        - リモートのブランチを表示させる場合、--all オプションが必要なので注意しましょう。
- あともう少しです。ローカル環境に、上記リモートブランチと紐づいた作業ブランチを作成しましょう。
    - コマンドの場合、`git branch feature/new_function/my_name origin/feature/new_function/my_name` 
- ローカル環境で、checkoutを行い、作業空間を上記作業ブランチに向けましょう。
    - コマンドの場合、`git checkout feature/new_function/my_name`
- 新しいブランチで作業をしてみましょう。作業を済ませたら、リモートサーバに変更をPushした上で、リモートサーバのUIからPull Requestをdevelopブランチに対し投げてみましょう。
- 最後に、Pull Requestに対して、自分自身でコメントしたり、承認したりしてみましょう。
    - 変更が develop ブランチに取り込まれたことを確認しましょう。

# さいごに
最後は詰め込みになってしまいましたが、ここまでの概要を理解し、実践すれば、Gitを用いた開発にひとまずは参加できると思います。

次のステップとして、より実践的な操作、コマンドを知りたい場合、書籍、[Git Reference](https://git-scm.com/docs)、Qiitaの他記事などを参考にしてみてください。

もし、手順漏れ、リンク切れなどに気付いた場合や、ご意見等ありましたら、是非お寄せください。
最後まで読んでいただきありがとうございました。