【Git】squash merge と rebase merge の挙動を確認してみた【雑記】

git のコミット履歴をまとめる ``squash``と、 ブランチを merge するときにあるブランチの先端に別のブランチを統合する ``rebase`` の挙動について確認してみました。

## 準備

ブランチを作る

```bash
> git checkout -b feature
> git branch
* feature
  main
```

適当なファイルを作成してコミットする

```bash
> touch date.txt
> date > date.txt
> git add date.txt
> git commit -m "add date.txt
```

ログを確認する

```bash
> git lol
* 5c78969 (HEAD -> feature) add date.txt
* 586cb56 (main) update
```

mainブランチでブランチを進める

```bash
> git checkout main
> echo "Hello world v2" > main.txt
> git commit -am "update"
```

ログを確認

```bash
> git lol
* 4e69dea (HEAD -> main) update
| * 5c78969 (feature) add date.txt
|/
* 586cb56 update
```

featureのブランチを1つ進める

```bash
> git checkout feature
> date > date.txt
> git commit -am "date update"
```

ログを確認

```bash
> git lol
* 886de2b (HEAD -> feature) date update
* 5c78969 add date.txt
| * 4e69dea (main) update
|/
* 586cb56 update
```

## squshでコミットをまとめる

featureでの2つのコミットを1つにまとめる

```bash
> git rebase -i HEAD~2
```

エディタが立ち上がるので、squashするコミットを選択する。

```diff
pick 5c78969 add date.txt
- pick 886de2b date update
+ s 886de2b date update

# Rebase 586cb56..886de2b onto 586cb56 (2 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
```

ログを確認する。
コミットが1つにまとまってhash値が変更されている。

```bash
> git lol
* 12f2b31 (HEAD -> feature) date update
| * 4e69dea (main) update
|/
* 586cb56 update
```

## rebase

mainブランチをfeatureブランチに取り込む

```bash
> git rebase main
```

ログを確認する。mainブランチの最新のコミットからfeatureが作られhash値も新しいものに変わった。

```bash
> git lol
* e9b7465 (HEAD -> feature) date update
* 4e69dea (main) update
* 586cb56 update
```


### リモートブランチをrebaseで取り込む

mainブランチのコミットを1つ進める

```bash
> git switch main
> echo "Hello world v3" > main.txt
> git commit -am "update"
> git push origin main
```

ログを確認

```bash
> git lol
* 25b1b5c (HEAD -> main, origin/main, origin/HEAD) update
| * e9b7465 (feature) date update
|/
* 4e69dea update
* 586cb56 update
```

リモートのmainブランチをrebaseして取り込む

```bash
> git switch feature
> git pull --rebase origin main
```

ログを確認する。
``git rebase main``と同様にfeatureブランチはmainブランチから続くようにコミット履歴が改変された。

```bash
> git lol
* ebef349 (HEAD -> feature) date update
* 25b1b5c (origin/main, origin/HEAD, main) update
* 4e69dea update
* 586cb56 update
```