【Git】rebaseが分からないのでゲーム形式で楽しく勉強した

新卒エンジニアです。

個人開発ではfeatureブランチを切って運用していますが、共同作業ではないので基本的にコンフリクトって発生しなくて`merge` をするだけで`rebase`使う機会がなかったのですが、企業エンジニアになって共同作業をしたとたんコンフリクト出したので、**Gitとrebaseをちゃんと勉強しなおさなきゃなぁ**と考えていました。

# Agenda
- [サービス紹介](#サービス紹介)
- [rebaseについて学んだこと](#rebaseについて学んだこと)
- [学習内容総アウトプット](#学習内容総アウトプット)
- [感想](#感想)

# サービス紹介
[Learn Git Branching](https://learngitbranching.js.org)というサイトを見つけました。

Gitのフローを可視化して、左側の到達目標と同じ形になるようにコマンドを入力していく。というサイトです。
左下にコンソールが出ています。到達目標は隠す事ができます。

![スクリーンショット 2018-04-11 13.11.41.png](https://qiita-image-store.s3.amazonaws.com/0/114709/af4b7859-4dd7-385a-dd85-e07e8e2dbcdb.png)

上の課題では以下のようなコマンドを入力しました。(この課題ではrebaseが出てこない)
![スクリーンショット 2018-04-11 13.21.14.png](https://qiita-image-store.s3.amazonaws.com/0/114709/fe7d4bb1-6b28-5c69-a501-0e9a541eebd2.png)

## 内容構成
MainとRemoteがあり、Mainは日本語化されておりローカルレポジトリの操作をメインに学ぶことができます。
Remoteではリモートレポジトリの操作を学ぶことができます。しかし、一部日本語化がされていないです。

Main
├ gitの基本的なコマンド群をほどよいペースで学ぶ
│ 　　　├  1. Gitのコミット
│ 　　　├  2. Gitのブランチ
│ 　　　├  3. ブランチとマージ
│ 　　　└  4. **Rebaseの解説**
├ 更にgitの素晴らしさを堪能しよう
│ 　　　├  1. HEADの分離
│ 　　　├  2. 相対リファレンス (^)
│ 　　　├  3. 相対リファレンス その2 (~)
│ 　　　└  4. 変更を元にもどす
├ **話題のrebaseってどんなものだろう？っていう人にオススメ**(これ！)
│ 　　　├  1. cherry-pick入門
│ 　　　└  2. **インタラクティブrebase入門**
├ gitを使う上での様々なtipsやテクニックなど
│ 　　　├  1. 一つのコミットのみを取得
│ 　　　├  2. コミットをやりくりする
│ 　　　├  3. コミットをやりくりする その2
│ 　　　├  4. Gitのタグ
│　　　 └  5. Git Describe
└  勇気ある人のみ！
　　　　├  1. 9000回以上のrebase
　　　　├  2. 複数の親
　　　　└  3. ブランチスパゲッティ

Remote
├ 自分のコードをより広く公開しましょう
│ 　　　├  1. Clone入門
│ 　　　├  2. リモートのブランチ
│ 　　　├  3. Git Fetch
│ 　　　├  4. Git Pull
│ 　　　├  5. 擬似的なチーム作業
│ 　　　├  6. Git Push
│ 　　　└  7. 履歴の分岐
└ 絶えず上級者の仕事は存在する。。。
 　　　├  1. Push Master!
 　　　├  2. リモートとのmerge
 　　　├  3. リモートのトラッキング
 　　　├  4. Git pushの引数(ここから日本語化が未実装)
 　　　├  5. Git pushの引数 -- 拡張編!
 　　　├  6. Fetchの引数
 　　　├  7. 無のsource
 　　　└  8. Pullの引数

## 良いところ
[猿でもわかるGit入門](https://backlog.com/ja/git-tutorial/)は、すごく分かりやすい記事でとてもお世話になりましたが、手を動かすものではないです。

しかし、こちらのサイトは**ステップバイステップで、手を動かしながら楽しく学べる**ので非常に頭に入りました。
目標と自分のフローがビジュアライズされていて一目で理解できるのも素晴らしいです。

## 面白いところ
回答後に、自分のコマンド回数と最短のコマンド回数が出るので
「正しい解法はどのようなものだったのだろうか？」と思ってSolutionを見るとこのような文章が出ます。

> どうしても正解がみたいですか?

> 頑張れ頑張れできるできる絶対できる頑張れもっとやれるって

> やれる気持ちの問題だ頑張れ頑張れそこだ！

> そこで諦めるな絶対に頑張れ積極的にポジティブに頑張る頑張る

> 北京だって頑張ってるんだから！
> |Cancel|　　　|Confirm|

## 所要時間
数時間程度。

## 学べなかったこと
ワークツリー、index、Git Repositoryなどでどのような動きがあるかは学べなかったです。
あくまでgitの利用方法に焦点を当てているようです。

それは[いつやるのGit入門](https://www.slideshare.net/matsukaz/git-17499005)でざっくりみました。

# rebaseについて学んだこと
## rebaseの基礎
Git rebaseは今いるブランチからrebaseしたいブランチを指定する。

- * bugFix C3
- master C2

```
> git rebase master
```

すると、masterのHEADの先に`C3'`という **C3のコピーコミットが作られる。**この時に忘れてはいけないのは、C3というコミットはまだ存在している。

## mergeとの違い
mergeは今いるブランチに別のブランチの差分を合わせて**新しいコミットを作る**

## rebase -i
インタラクティブリベース。

- コミットの順番を入れ替え
- 特定のコミットを含めない

などのリベースができる。

Macだとvimが立ち上がる。(vimの使い方はまだよくわかっていない...。)

# 学習内容総アウトプット

Gitは差分を扱い、軽量
親からの差分ファイルを扱う。

軽量なので早めに、かつ頻繁にブランチを切るのが大事。

ブランチをいっぱい作ってもストレージやメモリを全然使わないので、ブランチ肥大化よりも論理的な分割の方がメリットが大きい。

ブランチとは**特定のコミットを指示したポインタ**
ブランチとは
「あるコミットとその親のコミッタたちを含めた全てのコミット」

Git merge
二つの独立した親を持つ特別なコミットを作ることができる。

- bugfix
- master

があった場合、bugFixとmasterの二つのコミットを親に持つ新しいコミットを作ることができる。

git mergeは今いるブランチに、どのブランチをマージさせるか。という処理
(オプションによってどのブランチからどのブランチにという指定は可能)

Git rebaseのイメージは
「マージするコミットのコピーを取って、どこかにストンと落とす」

HEADとは、現在チェックアウトされているコミットを指す単語。
今作業中のコミットを表す。

HEADはいつも、作業中のツリーに反映されている最新のコミットを指す。
HEADは通常ブランチに紐づいている。
HEADの分離とは、特定のコミットにHEADを紐づけること。

HEAD^ などで、HEADの一つ前のコミットをcheckoutできる。
HEAD~3とすると、HEADの3つ前という使い方。

Git branch -f master HEAD~2 とすると、masterブランチ(ポインタが指し示すコミット)をHEADの2個前にする。ということ

Git resetはブランチのポインタを元に戻す。(Git Repositoryの状態にindexを合わせる)ローカルではうまくいく。

変更を巻き戻して他の人と共有するには、git revertを使う必要がある。
revertでは、打ち消したいコミットへの打ち消しコミットをする。ポインタを移動するだけではない。

git cherry-pick `コミット名1` `コミット名2` `コミット名3` で、特定のブランチにコミットをコピーする。


Git fetchは、リモートにあってローカルにないコミットをダウンロードするのに使う。
Git pullがしてるのは、実はリモートorigin/xxxの変更を持って来てローカルxxxブランチにマージしている。

Git pushでローカルの変更をリモートにpushする。

# 感想
ゲーム感覚で学べるのでよかったです。
rebaseがどのような働きをするのかが理解できました。

gitの内部の仕組みが気になってきたので、次は仕組みを勉強したいと思います。