超初心者のGitHub実験室_00：何度も簡単に実験しなおせる呪文を手に入れる（+おまけ実験）

# はじめに
この「超初心者のGitHub実験室」は、GitHub超初心者の私が、GitHubの動きを体感的に学ぶために行った実験のログになります。

今回は実験室をいつでもリセットできるおまじないの取得と、簡単なmerge、rebaseの挙動の確認をしてみました。
※実は、merge、rebaseについては、思いがけない動きをしないか期待してはいたのですが、そんなことはないですね。普通にmergeとrebaseの、当たり前のふるまいが確認できました。

それでは早速、実験室へ。。。


<details><summary> 補足：私の知識レベル</summary>

以下を「なんとなく理解できている」という状況です。それ以上のことは、これからこの実験しつで実践しながら理解していきたいと思っています。
  - GitHubって何ができるもの？
  - ローカルリポジトリ、リモートリポジトリの概念
  - ブランチの概念
  - 「ブランチを作成し、ローカルで変更を入れて、リモートブランチに反映させる」の一連の操作

</details>



## 実験室の整備
実験室というからには、似たようなことを何度も試行することになります。そこで、常に好きな状態までゼロリセットする呪文を用意することにしました。

:::note warn
注意：あくまで実験用の呪文です。自分一人だけの、壊れても困らないリポジトリ内での利用に止めましょう。

:::

### ゼロリセット呪文の用意手順
ご注意：呪文は reset コマンドを利用します。履歴も含めてゼロリセット（改ざん？）されてるので、上記注意の通り、一人で試せて壊れても困らないリポジトリで利用しましょう。

#### 1. ローカルのmainブランチを、呪文で実現したい「初期状態」にする

私はこんな状態を「初期状態」としました。
![初期状態.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/df62a7fd-5e6f-96d9-15e9-7d532c7a31f7.png)

#### 2. 「初期状態」を mainブランチのリモートリポジトリへ反映
ローカルの変更をリモートへ反映させるには、以下のコマンド３つを順に実行でしたね。
```
$ git add .
$ git commit -m "任意のコミットメッセージ"
$ git push
```

#### 3. 「初期状態」のコミットIDを確認
分かりやすいので短い形のコミットIDで確認します。
```
$ git log --oneline -1
```
これで出てくる左端の7文字が、呪文に必要な「コミットID」です。
![スクリーンショット 2023-12-01 034946.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/a5dc02f5-dbe4-d4b2-69d5-02e74f01c7ac.png)

#### 4. 呪文を作りあげる
ここまでできたら、あとは呪文を組み立てるだけ。
以下の「*******」の部分に、先ほど取得したコミットIDを当てはめれば完成です！
```
$ git checkout main
$ git reset --hard *******
$ git push -f origin main
```

#### 5. 念のため、ブランチを削除するコマンドも確認
実験の時にはブランチを作るときもあると思います。
そんな時のために、ブランチ削除のためのコマンドも手元に用意しておきましょう。

##### リモートブランチの削除コマンド
``` 
$ git push --delete origin ブランチ名
``` 

##### ローカルブランチの削除コマンド
```
$ git branch -D ブランチ名
``` 

#### 6. 用意したコマンドを組み合わせる
ここまでで用意したコマンドなどを組み合わせ、理想の初期化ができる呪文を作成しましょう。


<details><summary> 私の場合は、こんな感じになりました </summary>

mainブランチの初期化に加え、ブランチを削除と mainブランチからの再作成も一緒に実施したかったので少し長くなりました。
```
$ git checkout main
$ git reset --hard コミットID
$ git push -f origin main

$ git push --delete origin ブランチ１
$ git branch -D ブランチ１

$ git push --delete origin ブランチ２
$ git branch -D ブランチ２

$ git checkout main
$ git  checkout -b ブランチ１
$ git push --set-upstream origin ブランチ１

$ git checkout main
$ git  checkout -b ブランチ２
$ git push --set-upstream origin ブランチ２
```
</details>

# おまけ実験：mergeとrebaseを使ってみる
実験するための環境が整ったところで、早速実験を開始します。

## 実験内容
今回は以下の実験を行います。
それぞれの実験の開始時には必ず、先ほど作成したゼロリセットの呪文を唱えています。

| 実験番号  | 実験内容 | 実験図 |
| -------  | ------ | ------ |
| １    | <ol><li>初期状態から、Aブランチ、Bブランチそれぞれで変更をいれる</li><li>両ブランチを順番に main へ merge</li></ol> | ![実験1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/c9c90546-8fa7-6e2a-4490-51b1803eb477.png)|
| ２-１ | <ol><li>初期状態から、Aブランチ、Bブランチそれぞれで変更をいれる</li><li>Aブランチのみ main へ merge</li><li>その後、Bブランチに、main の変更を merge し</li><li> Bブランチの内容を main へ merge</li></ol> | ![実験2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/8308368c-17d2-9e0a-d394-e8835e6169bb.png)|
| ２-２ | <ol><li>初期状態から、Aブランチ、Bブランチそれぞれで変更をいれる</li><li>Aブランチのみ main へ merge</li><li>その後、Bブランチを rebase し</li><li>Bブランチの内容を main へ merge</li></ol> | ![実験2-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/b892d4fd-d1bb-f45c-7ac4-0c83b43db772.png)|
| ３ | <ol><li>初期状態から、Aブランチのみ変更をいれる</li><li>Aブランチを main へ merge</li><li>その後、Bブランチに main の変更を rebase し</li><li>Bブランチの内容を変更のうえ</li><li> Bブランチを main へ merge</li><li>Aブランチの先ほどのコミットを revert し</li><li>Aブランチの内容を main へ merge</li></ol> | ![実験3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/96381ceb-a25f-3315-23ea-37c8f49023c1.png)|

## 実験記録

### 実験1
![実験1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/c9c90546-8fa7-6e2a-4490-51b1803eb477.png)

初期状態では、A.txtもB.txtも空行2行のみ存在する状態。
feature/testA → A.txt
feature/testB → B.txt
を編集した。


| 手順 | main | feature/testA | feature/testB |
| --- | ---- | ---- | ---- |
| 1.初期状態から、Aブランチ、Bブランチそれぞれで変更をいれる | ![1-1main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/f442d401-8e38-63e3-8f4b-1bde756b1134.png) | ![1-1_A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/e84edeac-44e5-be19-e8d5-de460fd0f44e.png) | ![1-1_B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/a84c561c-0e64-d944-590d-6634d19fd99e.png) |
| 2.両ブランチを順番に main へ merge | ![1-2main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/944699d0-46b0-cf45-8f31-77e50864efee.png)| ![1-2_A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/e84edeac-44e5-be19-e8d5-de460fd0f44e.png) | ![1-2_B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/a84c561c-0e64-d944-590d-6634d19fd99e.png) |

実行したコマンド
```
## 手順1
$ git checkout feature/testA
$ git add .
$ git commit -m "実験1"
$ git push

$ git checkout feature/testB
$ git add .
$ git commit -m "実験1"
$ git push

## 手順2
$ git checkout main
$ git merge feature/testA
$ git push

$ git merge feature/testB
$ git push
```

### 実験2-1
![実験2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/8308368c-17d2-9e0a-d394-e8835e6169bb.png)

初期状態では、A.txtもB.txtも空行2行のみ存在する状態。
feature/testA → A.txt
feature/testB → B.txt
を編集した。

| 手順 | main | feature/testA | feature/testB |
| --- | ---- | ---- | ---- |
| 1.初期状態から、Aブランチ、Bブランチそれぞれで変更をいれる | ![2-1-1main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/3ea80f8f-c006-b0f5-814d-630ff71ee8ed.png) | ![2-1-1A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/bea10b36-be9c-957b-4e8d-5341035673c4.png)|![2-1-1B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/c2748266-d9d9-8354-67f6-1dfabc9b0dee.png) |
| 2.Aブランチのみ main へ merge |![2-1-2main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/7f0cf973-78bf-69cb-97df-408191d1991e.png) | ![2-1-2A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/bea10b36-be9c-957b-4e8d-5341035673c4.png)|![2-1-2B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/c2748266-d9d9-8354-67f6-1dfabc9b0dee.png) |
| 3.その後、Bブランチに、main の変更を merge し|![2-1-3main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/466c670f-ba1e-29c7-9730-11806e5c0901.png) |![2-1-3A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/bea10b36-be9c-957b-4e8d-5341035673c4.png) |![2-1-3B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/d5af7a9f-fa3a-4f4e-bbc4-afbfb285ffa1.png) |
| 4.Bブランチの内容を main へ merge | ![2-1-4main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/0d81cd74-4b0c-be77-f554-049f761c39f6.png)|![2-1-4A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/bea10b36-be9c-957b-4e8d-5341035673c4.png) |![2-1-4B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/d5af7a9f-fa3a-4f4e-bbc4-afbfb285ffa1.png) |

実行したコマンド
```
## 手順1
$ git checkout feature/testA
$ git add .
$ git commit -m "実験2-1"
$ git push

$ git checkout feature/testB
$ git add .
$ git commit -m "実験2-1"
$ git push

## 手順2
$ git checkout main
$ git merge feature/testA
$ git push

## 手順3
$ git checkout feature/testB
$ git merge main
$ git push

## 手順4
$ git checkout main
$ git merge feature/testB
$ git push
```

### 実験2-2
![実験2-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/b892d4fd-d1bb-f45c-7ac4-0c83b43db772.png)

初期状態では、A.txtもB.txtも空行2行のみ存在する状態。
feature/testA → A.txt
feature/testB → B.txt
を編集した。

| 手順 | main | feature/testA | feature/testB |
| --- | ---- | ---- | ---- |
| 1.初期状態から、Aブランチ、Bブランチそれぞれで変更をいれる | ![2-2-1main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/3ea80f8f-c006-b0f5-814d-630ff71ee8ed.png) | ![2-2-1A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/43ea6af2-725d-5258-271a-63b428bf157c.png) | ![2-2-1B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/8013f009-248b-4404-8211-3432ad9a7c60.png) |
| 2.Aブランチのみ main へ merge | ![2-2-2main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/48765e6b-81d2-d479-785a-913c2067c77a.png) | ![2-2-2A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/43ea6af2-725d-5258-271a-63b428bf157c.png) | ![2-2-2B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/8013f009-248b-4404-8211-3432ad9a7c60.png) |
| 3.その後、Bブランチを rebase し| ![2-2-3main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/48765e6b-81d2-d479-785a-913c2067c77a.png) | ![2-2-3A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/43ea6af2-725d-5258-271a-63b428bf157c.png) | ![2-2-3B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/fe958114-d446-b8bb-273d-7c520244db52.png) |
| 4.Bブランチの内容を main へ merge | ![2-2-4main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/4e8eab9e-5a74-b6fb-5eff-ca056c598fe4.png) | ![2-2-4A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/43ea6af2-725d-5258-271a-63b428bf157c.png) | ![2-2-4B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/fe958114-d446-b8bb-273d-7c520244db52.png) |

実行したコマンド
```
## 手順1
$ git checkout feature/testA
$ git add .
$ git commit -m "実験2-2"
$ git push

$ git checkout feature/testB
$ git add .
$ git commit -m "実験2-2"
$ git push

## 手順2
$ git checkout main
$ git merge feature/testA
$ git push

## 手順3
$ git checkout feature/testB
$ git rebase main
$ git push

## 手順4
$ git checkout main
$ git merge feature/testB
$ git push
```

### 実験3
![実験3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/96381ceb-a25f-3315-23ea-37c8f49023c1.png)

初期状態では、A.txtもB.txtも空行2行のみ存在する状態。
feature/testA → A.txt
feature/testB → B.txt
を編集した。

| 手順 | main | feature/testA | feature/testB |
| --- | ---- | ---- | ---- |
| 1.初期状態から、Aブランチのみ変更をいれる | ![3-1main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/3ea80f8f-c006-b0f5-814d-630ff71ee8ed.png) | ![3-1A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/a09066fa-8463-c4d6-db62-18a5ab37445a.png) |![3-1B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/3ea80f8f-c006-b0f5-814d-630ff71ee8ed.png) |
| 2.Aブランチを main へ merge | ![3-2main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/c100fa65-94f1-07ee-2618-76e827934e54.png)| ![3-2A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/a09066fa-8463-c4d6-db62-18a5ab37445a.png) |![3-2B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/3ea80f8f-c006-b0f5-814d-630ff71ee8ed.png) |
| 3.その後、Bブランチを rebase し| ![3-3main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/c100fa65-94f1-07ee-2618-76e827934e54.png)| ![3-3A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/a09066fa-8463-c4d6-db62-18a5ab37445a.png) |![3-3B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/c837ad27-9790-6a98-ad6d-1edeb762a1f2.png) |
| 4.Bブランチの内容を変更のうえ | ![3-4main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/c100fa65-94f1-07ee-2618-76e827934e54.png)| ![3-4A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/a09066fa-8463-c4d6-db62-18a5ab37445a.png) |![3-4B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/8d328b5c-43d1-e521-49c5-8f61d290d5c3.png) |
| 5.Bブランチを main へ merge | ![3-5main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/723f183d-c76b-e79b-34ce-53518b63381b.png)| ![3-5A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/a09066fa-8463-c4d6-db62-18a5ab37445a.png) |![3-5B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/8d328b5c-43d1-e521-49c5-8f61d290d5c3.png) |
| 6.Aブランチの先ほどのコミットを revert し | ![3-6main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/723f183d-c76b-e79b-34ce-53518b63381b.png)| ![3-6A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/205e3f2e-a429-28f3-09b2-b5088749dfed.png) |![3-6B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/8d328b5c-43d1-e521-49c5-8f61d290d5c3.png) |
| 7.Aブランチの内容を main へ merge | ![3-7main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/ebfceadf-4581-9a6e-3b30-bd509dc46086.png) | ![3-7A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/205e3f2e-a429-28f3-09b2-b5088749dfed.png) |![3-7B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984941/8d328b5c-43d1-e521-49c5-8f61d290d5c3.png) |

実行したコマンド
```
## 手順1
$ git checkout feature/testA
$ git add .
$ git commit -m "実験3"
$ git push

## 手順2
$ git checkout main
$ git merge feature/testA
$ git push

## 手順3
$ git checkout feature/testB
$ git rebase main
$ git push

## 手順4
$ git checkout feature/testB
$ git add .
$ git commit -m "実験3"
$ git push

## 手順5
$ git checkout main
$ git merge feature/testB
$ git push

## 手順6
$ git checkout feature/testA
$ git revert コミットID
$ git push

## 手順7
$ git checkout main
$ git merge feature/testA
$ git push
```

## 実験感想
一旦、初心者には使い慣れない以下３つを使って、どう作用するかが見られたので満足しています。

- merge
- rebase
- revert

ただ、巷で言われている、rebase と merge の本当の違いが見える部分までは達せなかったので、そちらは今後の実験に回します。
また、今回は、あまりトリッキーな実験手順は組まなかったこともあり、GitHub側の処理もソツなく完了しましたし、思いがけないマージのされ方やエラーもなく終わってしまいました。次回はもう少し、競合状態をあえて引き起こしたり、コミットログまで確認する実験をしてみたいと思っています。


# あとがき
実は今回、初のQiita記事のため、投稿する際にとても緊張しました。
あとは、内容に関係なくちょっとした部分ではありますが、アドベントカレンダーということもあり、実験図には赤と緑のクリスマスカラーを取り入れています。

なお、今回の実験を行うにあたり、勝手ながら以下の記事から学ばせていただきました。素敵な情報を残してくださった、エンジニア先輩の皆様にも感謝します。

- ゼロリセットする呪文を作ったときに学ばせていただいた記事
    - https://zenn.dev/yamadatt/articles/git-reset-push
    - https://qiita.com/mdstoy/items/6de0aaa06dcd0cc46102
- rebase や merge の違いの理解に苦しんだ際に読ませていただいた記事
    - https://qiita.com/minakawa-daiki/items/c8a939b5d529ee39eac1