粗くGitを理解する



## はじめに

Git使う機会がちょこちょこあるので、Gitの勉強メモをここに残す。
Gitガチ勢じゃないので、粗く理解するのが目標。


## 環境

本稿では、AWSのCodeCommit/Cloud9をリモート環境/ローカル環境として、Gitを理解していく。

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/8162a7e8-0400-284f-7f19-cbd0b7d3998f.png)


## Gitとは

- 『ファイルのバージョンを管理する』仕組み
- テキスト形式のファイルを管理
- バイナリデータは管理しちゃダメ
    - WordとかExcelとかNG
- バイナリデータを管理すると変更履歴がぐちゃぐちゃになるらしい
- 画像データもバイナリデータ
    - ※ 画像データは管理OKと考える人もいるらしい


## Git基本用語の確認

基本用語を粗く説明する。

- **リモート環境**
    - リモートリポジトリのあるところ
    - 本稿では、CodeCommit をリモート環境とする
    - ![図5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/59f41f85-e496-35fd-daa3-6f8c575fce1f.png)
- **ローカル環境**
    - ファイルの作成/変更する環境
    - 個人PCなどが該当する
    - 本稿では Cloud9 をローカル環境とする
    - ![図6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/cb1742c8-2225-fd08-f1ed-3f8dd68e89e4.png)
- **リポジトリ**
    - リポジトリとは、ファイルやディレクトリの状態を記録するところ
    - 変更履歴も覚えている
    - いつ、誰が、どこを変更したのか、が記録されてる
    - ロカールリポジトリ、リモートリポジトリの2種類ある
    - GitHubとかBitbucketとかリモートリポジトリを提供するサービス多数ある
    - ![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/74e3ea3b-b241-7c13-19f0-b3cdf76710ab.png)
- **ステージ**
    - ローカル環境にある
    - コミットする変更を準備するところ
    - git add コマンド実行でファイルがステージにはいる
    - ![図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/fa2bb417-fb31-244c-0dde-6082b1ca223d.png)
- **ワークツリー**
    - ローカル環境にある
    - ファイルを変更する作業場
    - ![図4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/711b4921-e237-0cff-0002-59c00cc2bbcd.png)
- **スナップショット**
    - その時点の状態を保存するバックアップ方法
    - 差分バックアップとは違い、全ての状態をバックアップする
    - （差分バックアップは変更部分のみ保存）
    - gitの変更履歴は、"圧縮→スナップショット"で保存してる
    - ※「スナップショット」は、gitの専門用語ではない
- **Gitオブジェクト**
    - 圧縮ファイル、ツリーファイル、コミットファイルのこと。
- **圧縮ファイル**
    - ファイルを圧縮したもの、blobオブジェクトという。
    - blobはカタマリという意味らしい
    - git add コマンドを実行すると作成される
- **ツリーファイル**
    - ファイル名の情報をもっている
    - 「treeオブジェクト」と言う
    - Gitは、圧縮ファイルとツリーファイルで、ファイルとファイル名を管理
- **コミットファイル**
    - いつ、誰が、何をしたかの情報をもっている
    - 「commitオブジェクト」という
- **コミット**
    - ファイルの変更を記録すること
    - git commitコマンドを使う
- **ブランチ**
    - 複数の機能を平行開発できる仕組み
    - 機能Aと機能Bを個別に開発する際に、
        - 機能Aの開発に機能Bの開発状況が影響しない
        - 機能Bの開発に機能Aの開発状況が影響しない
    - ブランチを作成することを「ブランチを切る」という
    - デフォルトのブランチ名を `master` という
    - コミットを指し示すポインタ
- **HEAD**
    - 今、どのブランチにいるかを指し示すポインタ
- **コンフリクト**
    - 同じ場所に複数の変更が発生した状態
- **プルリクエスト**
    - マージを依頼する
- **マージ**
    - 誰かが変更した内容を取り入れる
- **リベース**
    - 変更統合時に、履歴を整理
- **タグ**
    - コミットに名前を付与し、参照しやすくする。




## リポジトリのクローンの流れ

`git clone`でリポジトリをコピーするときの流れを粗く理解する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/2eb23b96-0196-65e7-c650-3e9c5f1b699c.png)


## ファイル変更からpushまでの流れ

ファイルをリモートリポジトリにpushするまでの流れを粗く理解する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/a003ee29-3af6-d9e3-749c-f6ebf9825c0e.png)

## 変更状況を確認する

`git status`コマンドで変更状況を確認できる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/b8f8f2ef-6b33-5f95-684b-cb4fd9fe5f45.png)



## ブランチとHEADおさらい

ブランチもHEADもポインタ
ブランチはコミットをしめすポインタ
HEADはブランチをしめすポインタ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/7917a8fa-c9a7-b3d8-8bdd-e16eedb051c0.png)


developというブランチを作り、developブランチに移動した場合、ブランチ,HEADがしめすところはこーなる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/b3a93b6b-72c0-af67-d1af-0ce664873e22.png)


developブランチでコミットしたら、こーなる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/30c53f6e-9a95-6ed7-73c3-03d5a6deb9c7.png)


機能別に平行開発する場合、機能別にブランチを作成したりする。

- 機能Aを開発する担当者 山田さんのHEADは、dev-FuncAブランチをしめす
- 機能Bを開発する担当者 鈴木さんのHEADは、dev-FuncBブランチをしめす

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/dc7bbff4-c868-e57f-11ef-148e153ba13f.png)

## マージ（Git Merge）

Gitマージとは、誰かが変更した内容を取り入れること。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/90c8d964-5a85-8ab9-bf9b-6ca158324835.png)

## リベース（Git Rebase）

Gitマージと同じで、誰かが変更した内容を取り入れること。
GitリベースはGitマージと異なり変更履歴も含め取り入れる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/48d9b2eb-1429-9d31-7267-36004af94966.png)




## Git基本コマンド

覚えておいた方がよさげなコマンドを列挙

|コマンド|概要|
|------------|-----------|
|git config  ||
|git init    | .gitディレクトリ作成 |
|git clone   | Gitリポジトリのコピー |
|git add     | 変更をステージに追加|
|git commit  | ステージにあげた変更をGitリポジトリに記録 |
|git status  | 現在の変更状況を確認 |
|git diff    |変更差分を表示|
|git diff --staged    |git add後の変更差分を表示|
|git log |変更履歴を表示|
|git log --oneline|変更履歴を1行で表示|
|git log -p {{xxx}}|ファイルの変更履歴を表示|
|git log -n |変更履歴を表示するコミット数を制限|
|git rm {{xxx}}|ファイル削除を記録|
|git rm -r {{xxx}}|ディレクトリ削除を記録|
|git rm --cached {{xxx}}|ファイル削除を記録し、かつファイルを残す|
|git mv {{元ファイル}} {{新ファイル}}|ファイル移動を記録|
|git remote add origin {{リモートリポジトリURL}}|リモートリポジトリを新規追加|
|git push|ローカルリポジトリの情報をリモートリポジトリにアップ|
|git config --global alias.xx {{Gitコマンド}}|コマンドにエイリアスを設定(commit = ci)|
|git checkout|ファイルへの変更を取り消す|
|git reset HEAD {{xxx}}|ステージした変更を取り消す|
|git commit --amend|直前のコミットを修正 ※pushしたコミット直すのNG|
|git rebase {{ブランチ名}}|履歴整理。ブランチの基点のコミットを別コミットに移動|
|git tag|コミットに名前を付与|
|git tag -a {{タグ名}} -m "{{メッセージ}}"|注釈付きタグ|
|git tag {{タグ名}}|軽量版タグ|
|git show {{タグ名}}|タグのデータを表示|
|git push {{リモート名}} {{タグ名}}|タグをリモートリポジトリに送信|
|git push {{リモート名}} --tags|全タグをリモートリポジトリに送信|
|git stash|作業を一時避難|
|git stash list|避難した作業を確認|
|git stash apply|避難した作業を復元|
|git stash apply --index|ステージの状況も復元|
|git stash apply {{スタッシュ名}}|特定の作業を復元|
|git stash apply stash@{XX}|特定の作業を復元|


## エイリアス設定例

よく使うコマンドは、エイリアスを設定し、短いコマンドを用意すると便利らしい。

```console
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.br branch
git config --global alias.co checkout
```

## .gitignore

バージョン管理したくないファイルを設定する。
パスワード情報のあるファイルとかバイナリファイルを設定するらしい。
.gitignoreファイルを作成し、管理しないファイルを設定する

例）画像や動画データをバージョン管理しない

```text:.gitignore
*.mp4
*.png
*.jpg
*.ts
```


## GitHub Flow

`GitHub Flow`とは、GitHub社のワークフロー
`GitHub Flow`を維持する規則

- masterブランチは常にデプロイできる状態にする
- 新開発はmasterブランチから新しいブランチを作成する
- 作成した新しいブランチ上で作業をコミットする
- 定期的にPushする
- masterにマージするためにプルリクエストを使う
- 必ずレビューを受ける
- masterブランチにマージしたらすぐデプロイする（テストとデプロイは自動化）