1からアプリケーションを作るエンジニアリングマネージャーの姿：Gitのお勉強編

## 目的
1. エンジニアリングマネージャーをやっているが、あまりにもエンジニアリングがわかっていない
     - 作業者として実務を行った経験しかなく、0から開発ができない
     - 開発環境の構築とは？
     - アーキテクチャの選定とは？
     - Gitの使い方を忘れている... etc
     - -> これでEMを名乗るのは恥ずかしい
1. 作ってみたいアプリがあるので、それを作って生活をリッチにする


## そもそもGitとは
ソースコードを含むドキュメントを管理するツール。ざっくり言えば、以下のことを教えてくれる。
 - こういう文章（フォルダ／ファイル）が増えましたよ
 - こういう文章（フォルダ／ファイル）が消えましたよ



## Gitの前提
Gitを理解するには、以下の2つの概念を知る必要がある。
1. ローカルとリモート
1. バージョン管理とブランチ
順を追って説明する

### 1. ローカルとリモート
 - ローカルは自分のPCのことで、リモートはGitのサーバーのこと
 - ローカルに（Gitを経由して）ファイルを保存することをCommitといい、リモートに保存することをPushという
 - リモートに保存すると、自分とPCを共有していない人（同僚や世界中の人）もドキュメントを見られるようになる

※ 直接リモートに保存することはできないので、必ずCommit -> Push の手順になる
※ ローカルからリモートに押し出すイメージでPushと呼んでいる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441429/f45a87cb-d8f3-c3f5-08d3-eb17c0990cb6.png)

### 2. バージョン管理の思想
 - バージョン管理とは、「正しいコードベース（ドキュメント）を定義して保存する」こと
     - たとえば（後述の）mainブランチは、正しいと検証されたコードベースの集合体
 - 本当は正しいコードベースだけを保存したいのだが、
     - 複数人で協働作業をしていると何が正しいのかわからなくなるし
     - 人間だから間違いもある

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441429/cee1554d-9554-6aac-b476-82d98633fc80.png)

 - Gitでは間違えたときの解消方法をたくさん提供している
     - Conflict（競合）の解消
     - Revert（過去のバージョンへの切り戻し）
     - 変更履歴の保存


## Gitの機能
### Commit
ローカルPCに、Gitを経由して（つまりバージョン管理する状態で）ファイルを保存すること
切り戻しというバージョン管理本来の目的を発揮するために、Commitはこまめに、小さい単位で行うことが望ましい

### Push
ローカルPCに保存されたファイルを、Gitのサーバー上で保存してもらうこと

### ステージング（Staging）
 - どこで機能するか
     - ローカル
 - これはなに
     - 変更があったファイルと、コミットするファイルを仕切る概念
 - なぜやるか
     - 一度に大量の作業を行った場合、コミット量も多くなる
     - 一方コミットはスモールかつ一定の単位で行われることが理想的
     - そのため、瞬間的に以下の2つを切り分ける必要が生じる
         1. 変更があった && 今すぐコミットするファイル
         1. 変更があった && でも今はコミットしないファイル


### リセット（Reset）
 - どこで機能するか
     - ローカル
 - これはなに
     - 誤ってローカルから削除してしまったファイルを、Commitする前に復活させる機能
     - Soft, Mixed, Hardの3タイプがある
 - なぜやるか
     - うっかりミスでローカルからファイルを削除してしまうことがあるため
     - 他の手段としてバージョンを切り戻して対応することも可能


### 無視する（Git Ignore）
 - どこで機能するか
     - ローカル
 - これはなに
     - Gitで管理する必要のないファイルを指定して、リポジトリに追加されないようにする
     - ログファイル（.log）や環境設定ファイル（.env）バイナリファイル（.exe、.dll）などはバージョン管理する必要がなかったりする
     - Ignoreするパターンも設定できる
 - なぜやるか
     - リポジトリが不要なデータで膨らむのを防ぐことができる
     - 類似機能として、「追跡から外す」というのもあるが、これは今回は書かない


### タグづけ（Tag）
 - どこで機能するか
     - （両方。説明に関係ない）
 - これはなに
     - コミットに対して、タグをつける機能
     - つけ方は英語で短くつける場合が多い
 - なぜやるか
     - 重要なコミットを識別し、検索したりジャンプしたりできるようにするため


### ブランチを作る
 - どこで機能するか
     - （両方。説明に関係ない）
 - これはなに
     - 機能や作業者など、任意の単位で、作業するコードベースを隔離する機能
 - なぜやるか
     - 複数人で作業をしていると、「Aさんの作業内容が全体（Bさん、Cさん、Dさん）に、リアルタイムに影響を及ぼしてしまう」という状態が発生する
         - Google Documentを複数人でリアルタイム編集しているときのカオス感をイメージしてほしい
     - 個々人（あるいは個々の機能）ごとにブランチを切って作業をすることで、影響がリアルタイムに及ぶのを防ぐ


### Merge
 - どこで機能するか
     - （両方。説明に関係ない）
 - これはなに
     - 複数のブランチを1つに統合すること（大体は、1つの派生ブランチを大元のブランチに統合する）
 - なぜやるか
     - 機能や作業者などの、任意の単位でどんどん開発を進めていくと、全体での整合性が取れなくなっていく
     - そのため、一定のタイミングで統合して、全体との足並みをそろえる必要がある


### Confilict（競合）の解消
 - どこで機能するか
     - （両方。説明に関係ない）
 - これはなに
     - 個別の作業と、全体（他の機能・他の人）との間で発生した差異を解消する
     - どちらかの作業を削除するか、両方取り込めるような新しい作業を追加するか
 - なぜやるか
     - 個別に作業をしていると、全体（他の機能・他の人）の作業と齟齬が発生する
     - 「どちらの作業が全体として正しいのか？」を判断し、より正しいコードベースを保存するため


### ブランチの削除
 - どこで機能するか
     - ローカル、リモート
 - これはなに
     - mergeが終わったあとのブランチを削除すること
 - なぜやるか
     - 統合されたあとのブランチは、変更内容が大元に反映されているため差分のない状態になり、不要になる
     - 残しておくと不必要な混乱のもとになるので、削除する



## その他
### コミットメッセージの書き方
 - [Gitのコミットメッセージの書き方](https://qiita.com/itosho/items/9565c6ad2ffc24c09364)を参考に考えてみた
     - 1行目は [ コミット種別 ]  要約

        | 種別 | 内容 |
        | ---- | ---- |
        | add | 新しいソースコードの追加 |
        | fix | バグ修正による既存ソースコードの変更 |
        | update | 機能追加による既存ソースコードの変更 |
        | remove | ファイルの削除 |


     - 2行目は空行
     - 3行目は変更した理由および拝啓と、その内容を詳細に記す


### ブランチ戦略
 - ブランチには大きく分けて3つの思想（スタイル）がある
 - 今回はGit Flowだけ説明
      - Git Flow
         | ブランチ名　| 主な目的 | 更新元 | 存在期間 | 正しさの程度 |
         | ---- | ---- | ---- | ---- | ---- |
         | main |本番環境用 | releaseやhotfixからのマージ | 永続的（常に存在） | 直接ユーザーに提供できるくらい正しい |
         | release | リリース前の最終調整やバグ修正 | developの集合体 | 一時的（リリース準備期間のみ存在） | リリース前にしかわからないバグが見つかってもよい |
         | develop | 開発中の機能の統合とテスト | featureの集合体 | 永続的（常に存在） | テストを通してバグが見つかってもよい |
         | feature | 新機能の実装 | developからpull | 一時的（特定の機能開発が完了するまで存在） |  開発バグがたくさんあってもよい |
 - 他にも、よりシンプルな、GitLab Flow、GitHub Flowなどがある