【勉強用】Gitのコマンドを実際に動かしてみた（③ブランチ編）

# はじめに

今回はGitのコマンドを実際に動かして、バージョンの確認や変更について理解を深めたいと思います。参考図書はこちらの[**動かして学ぶ！Git入門**](https://www.shoeisha.co.jp/book/detail/9784798170855)を使用しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3523467/927467bd-3ee8-bff3-c016-81d24c7d4cb0.png)

# コマンド

### 19. git branch
このコマンドを実行すると、現在あるブランチの一覧と、どのブランチにいるか（HEADがどのブランチに乗っているか）が表示されます。

それでは、実行して確認してみましょう。
```Git:Git Bash
$ git  branch
* main
```
現在は`main`といブランチにいることが分かりました。

### 20 . git branch ブランチ名
このコマンドを実行すると、指定した名前のブランチを作成できます。

それでは`practice`というブランチを作成してみましょう。

```Git:Git Bash
$ git branch practice
$ git branch
* main
  practice
```
新たに`practice`ブランチを作成できました。このコマンドではHEAD自体は移動しません。また`-v`オプションを加えるとブランチの先端があるコミットの情報も表示されます。

それでは実行してみましょう。
```Git:Git Bash
$ git branch -v
* main     0e420a2 Have a nice day !
  practice 0e420a2 Have a nice day !
```
`practice`ブランチにはまだ何もコミットしていないので、`master`ブランチと同じコミットとなります。

### 21. git checkout ブランチ名
このコマンドはブランチ間を移動する際に使用するコマンドです。

それでは、`main`ブランチから`practice`ブランチに移動してみましょう。

```Git:Git Bash
$ git checkout practice
Switched to branch 'practice'

$ git branch
  main
* practice
```
`main`ブランチから`practice`ブランチに移動することが出来ました。

ただし、ここで注意が必要です。現在いるブランチにコミットしていないステージングや作業ツリーが存在する際にブランチを移動すると、Gitがエラーを検知して切り替えをやめてしまいます。**変更が失われてしまう**可能性があるためです。


### 22. git commit （他ブランチ）
他ブランチに移動した後に、変更をコミットすると移動元のブランチを変更することなく、移動後のブランチを伸ばすことが出来ます。

それでは新たに`prac.txt`を作成し、`practice`ブランチにコミットし、HEADが移動したか確認してみましょう。

```Git:Git Bash
#prac.txtを作成
$ git add prac.txt
$ git commit -m "commit prac.txt"
[practice ba022a9] commit prac.txt
 1 file changed, 1 insertion(+)
 create mode 100644 prac.txt

$ git log
commit ba022a93f4b5b1c7a5572ae3b62b7d155b750e6b (HEAD -> practice)
Author: HANAKO <hanako@sample.com>
Date:   Sat Nov 4 06:19:35 2023 +0900

    commit prac.txt

commit 0e420a2f7324894fe09791f137d93d3fa3e07959 (main)
Author: HANAKO <hanako@sample.com>
Date:   Fri Nov 3 20:36:10 2023 +0900

    Have a nice day !

commit aa365952d8d38be4538bde4703f51ca27e76c98e
Author: HANAKO <hanako@sample.com>
Date:   Fri Nov 3 20:32:42 2023 +0900

    Enjoy !

commit 714ed154be5186cca4f5fc1b540526fb207ccb2a
Author: HANAKO <hanako@sample.com>
Date:   Fri Nov 3 15:30:56 2023 +0900

```
無事、`practice`ブランチにコミットすることが出来ました。

### 23. git log --all --graph
このコマンドを実行すると、ブランチの移動を考慮したコミットの流れを視覚的に表示します。

それでは、これまでのコミットの流れを確認してみましょう。


```Git:Git Bash
$ git log --all --graph
* commit ba022a93f4b5b1c7a5572ae3b62b7d155b750e6b (HEAD -> practice)
| Author: HANAKO <hanako@sample.com>
| Date:   Sat Nov 4 06:19:35 2023 +0900
|
|     commit prac.txt
|
* commit 0e420a2f7324894fe09791f137d93d3fa3e07959 (main)
| Author: HANAKO <hanako@sample.com>
| Date:   Fri Nov 3 20:36:10 2023 +0900
|
|     Have a nice day !
|
* commit aa365952d8d38be4538bde4703f51ca27e76c98e
| Author: HANAKO <hanako@sample.com>
| Date:   Fri Nov 3 20:32:42 2023 +0900
|
|     Enjoy !
|
* commit 714ed154be5186cca4f5fc1b540526fb207ccb2a
| Author: HANAKO <hanako@sample.com>
| Date:   Fri Nov 3 15:30:56 2023 +0900
|
|     check status
```
視覚的にコミットの流れが分かりましたね。またコミットの流れ自体を見たいときは、`--oneline`オプションを追加します。

それでは、実行してみましょう。
```Git:Git Bash
$ git log --all --oneline
ba022a9 (HEAD -> practice) commit prac.txt
0e420a2 (main) Have a nice day !
aa36595 Enjoy !
714ed15 check status
e6e9a3b first commit
```
先ほどより見やすくなりましたね。詳しいコミットの状態も確認したいときは`--graph`、流れを確認したいときは`--oneline`オプションを加えると良さそうです。

### 24. git merge 取り込みたいブランチ名
Gitを使った開発では、一般には**masterブランチが開発の主軸**で、最終的な成果は基本的にこのブランチに作り上げます。そのため最終的には、開発専用のブランチやエラー修正専用のブランチを`master`ブランチに取り込む必要があります。このときに行うコマンドが**git merge**です。

それでは、`practice`ブランチに新たに`merge.txt`を作成し、コミットします。その後、その変更を`main`ブランチにマージしてみましょう。
```Git:Git Bash
#practiceブランチにmerge.txtを追加
$ git add merge.txt
$ git commit -m "commit merge.txt"
[practice c691967] commit merge.txt
 1 file changed, 1 insertion(+)
 create mode 100644 merge.txt

$ git checkout main
Switched to branch 'main'

$ git merge practice
Updating 0e420a2..c691967
Fast-forward
 merge.txt | 1 +
 prac.txt  | 1 +
 2 files changed, 2 insertions(+)
 create mode 100644 merge.txt
 create mode 100644 prac.txt
```
無事、`practice`ブランチを`main`ブランチにマージすることが出来ました。

また、**git log --all --oneline**でブランチの状態を確認してみましょう。

```Git:Git Bash
$ git log --all --oneline
c691967 (HEAD -> main, practice) commit merge.txt
ba022a9 commit prac.txt
0e420a2 Have a nice day !
aa36595 Enjoy !
714ed15 check status
e6e9a3b first commit
```
HEADが`main`ブランチと`practice`ブランチに重ねっているのが確認できます。

### 25. コンフリクトの修正
マージするとき、一方のブランチでの変更箇所が他方のブランチの変更箇所と重なっていると、自動での変更適用が失敗します。この状態を**コンフリクト**といいます。どちらの変更を適用するのかGitには判別できないので、ユーザが適用結果を教えてやる必要があります。

それでは、`main`ブランチの`hello.txt`には`Yeah!`という文章を、`practice`ブランチのほうには`Hoo!`という文章を追加し、それぞれコミットしてから`main`ブランチにマージしてみましょう。

```Git:Git Bash
mainブランチのhello.txtに`Yeah!`という文章を追加
$ git add hello.txt
$ git commit -m "Yeah !"
[main 8ba08a1] Yeah !
 1 file changed, 2 insertions(+), 1 deletion(-)

#practiceブランチのhello.txtに`Hoo!`という文章を追加
$ git add hello.txt
$ git commit -m "Hoo.txt"
[practice 1ca01f9] Hoo.txt
 1 file changed, 2 insertions(+), 1 deletion(-)

#mainブランチに移動
$ git merge practice
Auto-merging hello.txt
CONFLICT (content): Merge conflict in hello.txt
Automatic merge failed; fix conflicts and then commit the result.
```
無事（？）コンフリクトが発生しました。

それでは、コンフリクトの内容を確認してみましょう。`hello.txt`の中身を確認してみましょう。

```Git:hello.txt
hello!
Hello, everyone!
Have a nice day !
<<<<<<< HEAD
Yeah !
=======
Hoo !
>>>>>>> practice
```
ここでは`=======`を境にHEAD（ここでは`main`ブランチ）に`Yeah !`という変更、`practice`ブランチに`Hoo !`という変更が加えられていることが分かります。

それでは、`Hoo !`という文章を削除して再度マージしましょう。
```Git:Git Bash
#hello.txtからHoo !という文章を削除
$ git add hello.txt
$ git commit -m "resolve conflict"
[main b79fc14] resolve conflict
```
`hello.txt`の中身を再度確認してみましょう。

```Git:Git hello.txt
hello!
Hello, everyone!
Have a nice day !
Yeah !
```
無事マージされましたね。

#### 補足：
コンフリクトが起きたときには、作業ツリーも、ステージも、.gitディレクトリ内も**マージの途中**になっています。コンフリクトの解消も行わずに、**マージ自体を取りやめたい**場合は**git merge --abort**を実行します。これを実行すると、マージ前の状態に戻してくれます。

### 26. git branch -d
これはブランチを削除するコマンドです。これは削除したいブランチ外にいないと実行できません。

それでは`practice`ブランチを削除してみましょう。
```Git:Git Bash
$ git branch -d practice
Deleted branch practice (was 1ca01f9).

$ git branch
* main
```
無事に、`practice`ブランチを削除できましたね。

### 27. 早送りマージ
これは変更を取り込むブランチ先端が、取り込まれるブランチ先端の祖先である場合に可能なマージです。**早送りマージ**は**マージコミットを作らずにポインタを進める**だけで済ませます。原理上コンフリクトは発生しません。

それでは、`practice2`ブランチを作成し、"prac2.txt"を作成した後、早送りマージしてみましょう。
```Git:Git Bash
#practice2ブランチでprac2.txtを作成
$ git add prac2.txt
$ git commit -m "commit prac2.txt"
[practice2 3d2ad50] commit prac2.txt
 1 file changed, 1 insertion(+)
 create mode 100644 prac2.txt

$ git checkout main
Switched to branch 'main'

$ git merge practice2
Updating b79fc14..3d2ad50
Fast-forward #早送りマージが行われている
 prac2.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 prac2.txt
```
無事に早送りマージが行われていますね。

# まとめ
今回の記事では、ブランチの操作を中心に学習しました。次回はタグの扱いについて学習したいと思います。

[**前回：【【勉強用】Gitのコマンドを実際に動かしてみた（②コミット編）**](https://qiita.com/Yuhei0531/items/ad69b53622225bcafcac)
[**次回：【勉強用】Gitのコマンドを実際に動かしてみた（④タグ編）**](https://qiita.com/Yuhei0531/items/36eb32f1dd85c303d3f3)

# 参考文献
[動かして学ぶ！Git入門](https://www.shoeisha.co.jp/book/detail/9784798170855)