CI/CDをkatacodaで体験（初心者向け） - Part3

# CI/CD入門
このぺーじでは、[katacoda](https://www.katacoda.com/)と呼ばれる「ブラウザから無料で勉強用のインスタンスを起動できるWebサービス」を利用してCI/CDを実践します
内容は上記リンクに沿うので、不明点があればそちらへどうぞ

## Gitのバージョン管理について - scenario3
ここでは、CI/CDとして欠かせないGitによるバージョン管理について学習します
このシナリオで学習することをさっと確認する場合は**概要**を確認
**理解に間違い等がございましたら、ぜひご指摘ください**

### <font color="Red">概要</font>
>- ```git remote <add/rm..etc>```でリモートレジストリを登録、削除
- ```git push <remote registry> <branch on remote registry>```で現在のbranchをリモートレジストリのブランチに反映
- ```git pull ```でローカルレジストリにリモートレジストリとの差分を反映。branchの指定可能
- ```git pull```=```git fetch```+```git merge``` 

### Step 1 - Git Remote
```git remote <add/rm..etc>```で現在のローカルレジストリとリモートレジストリの関係を定義できる
まず、現在のローカルレジストリがリモートレジストリを定義していないことを確認

```
$ ls -a
.  ..  .git  staging.txt
$ cd .git/
$ ls -a
.   branches        config       HEAD   index  logs     refs
..  COMMIT_EDITMSG  description  hooks  info   objects
$ cat config
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
```

続いて、リモートレジストリの登録

```
git remote add origin /s/remote-project/1   ///"s/remote-project/1"はGitHubのリモートレジストリ
```

このコマンドの実行前にいくつかの要件を満たす必要がある
>- GitHubにアカウントを持つ
- リモートレジストリが存在している
- リモートレジストリにアクセスできる
    - リモートレジストリの状態:public × https接続できるように設定されている
    - リモートレジストリの状態:private × ssh接続できるように設定されている

```
$ cd .git/
$ ls -a
.   branches        config       HEAD   index  logs     refs
..  COMMIT_EDITMSG  description  hooks  info   objects
$ cat config
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = /s/remote-project/1
        fetch = +refs/heads/*:refs/remotes/origin/*
```

新しく```[remote "origin"]```という項目が作成されている
ちなみにリモートレポジトリは複数設定可能

```
$ git remote add testOrigin /test/test
$ cat config
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = /s/remote-project/1
        fetch = +refs/heads/*:refs/remotes/origin/*
[remote "testOrigin"]
        url = /test/test
        fetch = +refs/heads/*:refs/remotes/testOrigin/*
```

### Step 2 - Git Push
一般的な開発では、複数人がそれぞれの担当を持っており、担当箇所の作成および編集を行う。その後、全体のコードやファイルに変更を組み込みます。
そのため、個人が担当部分に修正を加えたファイルをローカルレポジトリに反映させた後、リモートレポジトリにも反映させる必要がある。
リモートレポジトリにローカルレポジトリの状態を反映させるコマンドは
```git push <事前に設定したremoteレポジトリ> <branch>```

>**補足 ~branchとは？~**
Gitにはbranchと呼ばれる概念があります
branchには、主に、branchを「切る（追加する）」、「マージ」の操作があります
前者は、Gitのバージョン管理が行われているすべてのディレクトリに対して複製を作成
後者は、複製されたbranchの変更部分をmaster branchに反映させる
masterと呼ばれるbranchは自動生成され、今までの課題はこのmaster branch上で行っていた
**使い方（メリット）**
>>- （ローカル）レポジトリを複数人で利用する場合、個々人の変更がお互いに作用しない
>>- 編集内容に合わせて、branchを複製することでエラー処理の場合分けを容易にする

```
$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 228 bytes | 228.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /s/remote-project/1
 * [new branch]      master -> master
```

### Step 3 - Git Pull
Step 2では、ローカルレジストリの変更をリモートレジストリに反映させた
Step 3では、リモートレジストリの変更をローカルレジストリに反映させる
コマンドはこちら```git pull <remote registry> <branch>```

```
$ git pull origin master
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 4 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
From /s/remote-project/1
 * branch            master     -> FETCH_HEAD
   cbc1f59..6d9ea7e  master     -> origin/master
Updating cbc1f59..6d9ea7e
Fast-forward
 new-file.txt | 1 +
 staging.txt  | 1 +
 2 files changed, 2 insertions(+)
 create mode 100644 new-file.txt
```

### Step 4 - Git Log
Step 3にて、リモートレジストリの変更をローカルレジストリに反映させたので、変更箇所を確認
まずは、「誰が」、「いつ」、「どのような変更（コミット時のコメント）」を確認するため、```git log```

```
$ git log
ESC[33mcommit 6d9ea7e2001c3b962a947e7e7dfa6b3699766c09ESC[mESC[33m (ESC[mESC[1;36mHEAD -> ESC[mESC[
Author: Different User <DifferentUser@JoinScrapbook.com>   //「誰が」
Date:   Sat Oct 10 11:28:56 2020 +0000   //「いつ」

    Fix for Bug #1234   //「どのような変更（コミット時のコメント）」

ESC[33mcommit cbc1f598936938a50dd6d120c8271eaa707b3485ESC[m
Author: Katacoda Scenario <scenario@katacoda.com>   //私たちは、katacodaが用意したローカルレジストリにリモートでアクセスしている（なんだか不思議ですね（笑））
Date:   Sat Oct 10 11:28:38 2020 +0000

    Message
```

続いて、具体的にどのような変更が加えられたのか```git show```で確認

```
$ git show
ESC[33mcommit 6d9ea7e2001c3b962a947e7e7dfa6b3699766c09ESC[mESC[33m (ESC[mESC[1;36mHEAD -> ESC[mESC[
Author: Different User <DifferentUser@JoinScrapbook.com>
Date:   Sat Oct 10 11:28:56 2020 +0000

    Fix for Bug #1234

ESC[1mdiff --git a/new-file.txt b/new-file.txtESC[m    //変更されたファイル
ESC[1mnew file mode 100644ESC[m
ESC[1mindex 0000000..96716fbESC[m
ESC[1m--- /dev/nullESC[m
ESC[1m+++ b/new-file.txtESC[m
ESC[36m@@ -0,0 +1 @@ESC[m
ESC[32m+ESC[mESC[32mNewESC[m   //変更されたコード
ESC[1mdiff --git a/staging.txt b/staging.txtESC[m   //変更されたファイル
ESC[1mindex c4eb839..b0f03f3 100644ESC[m
ESC[1m--- a/staging.txtESC[m
ESC[1m+++ b/staging.txtESC[m
ESC[36m@@ -1 +1,2 @@ESC[m
 Staging AreaESC[m
ESC[32m+ESC[mESC[32mSomething ChangedESC[m   //変更されたコード
```

```git show```の味方が分からないので、何が変わったのかこちらで確認

```
$ ls -a
.  ..  .git  staging.txt

~~~git pull~~~

$ ls -a
.  ..  .git  new-file.txt  staging.txt
$ cat staging.txt
Staging Area
Something Changed
$ cat new-file.txt
New
```

二つの結果から、以下の変更箇所がある
```New```と記載された```new-file.txt```が新規作成
```Something Changed```と```staging.txt```に加筆

```git show```の結果の見方が分からん、、、、涙
誰か分かりやすく教えてください

### Step 5 - Git Fetch
```git pull```に似ている機能として```git fetch```があります
端的な違いはというと、**```git pull```=```git fetch```+```git merge```**です

```git pull```の処理は、リモートレジストリとの差分をローカルレジストリの**（master branchに）**反映させる
```git fetch```の処理は、リモートレジストリとの差分をローカルレジストリの**（origin/master branchに）**反映させる
```git merge```の処理は、ローカルレジストリの**master branch**に**origin/master branch**(※1)の差分を反映させる

※1
"remotes/origin/master"として説明されたりされなかったりする
違いをご存じの方、ご連絡を！！！

>**注意 ~```git merge(pull)```で頻発するエラー「コンフリクト」~**
発生原因：元となる状態から分岐（ブランチの追加、リモートレポジトリからのpull等）で同一ファイルに対して、別々の変更を加える。その後、元となる状態にそれぞれが変更を反映させることで競合が発生

>対応策：たくさんあるのでググりましょう（笑）
>>e.g.1)
>>1. 元となる状態を自分の状態に反映させる（リモートレジストリからpull、masterブランチからブランチ追加等）
>>2. 自分の変更箇所を追加する
>>3. 元となる状態にマージ（リモートレジストリにpush、masterブランチに追加したブランチをmerge）

>こちらの方法は、自分で加えた変更を一度破棄する必要があるので、変更箇所が複雑な場合は、次の方法を試すといった方針が適当かと思われる
>>e.g.2)
>>1. 自分の状態をmasterブランチにマージ
>>2. 元となる状態をひとまずfetch
>>3. 自分の状態と元となる状態の比較
>>4. 自分の状態を残すために、ブランチ追加
>>5. （以下e.g.1と以下同じ流れ）

**(remotes)/origin/master branchとは？**
リモートレジストリとローカルレジストリの中間に存在するbranchのこと
リモートレジストリとローカルレジストリの差分を確認したいけど、反映はさせたくない時に利用
e.g) 同じファイルについて、異なる人が編集を加えている場合

```
$ git branch -a
* ESC[32mmasterESC[m
$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 228 bytes | 228.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /s/remote-project/1
 * [new branch]      master -> master
$ git branch -a
* ESC[32mmasterESC[m
  ESC[31mremotes/origin/masterESC[m
```

上の結果から分かる通り、```git push```直後に(remotes)/origin/master branchが作成されている

```
$ git fetch origin master
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 4 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
From /s/remote-project/1
 * branch            master     -> FETCH_HEAD
   a5fb2d2..1f07849  master     -> origin/master
$ ls -a
.  ..  .git  staging.txt
$ git merge origin/master
Updating a5fb2d2..1f07849
Fast-forward
 new-file.txt | 1 +
 staging.txt  | 1 +
 2 files changed, 2 insertions(+)
 create mode 100644 new-file.txt
$ ls -a
.  ..  .git  new-file.txt  staging.txt
$ git branch -a
* ESC[32mmasterESC[m
  ESC[31mremotes/origin/masterESC[m
```

上の結果から分かる通り、```git merge```前後で```new-file.txt```が同一ディレクトリに出現
この部分の操作では、同一branch上で操作しているので分かりにくいが、fetch直後に```git checkout (remotes)/origin/master```でbranchを変更すると```new-file.txt```が存在していることが確認できる