git rebase の使い方を覚える

## 記事を書くきっかけ
ゴールデンウイークにgitのハンズオン勉強会に参加していました。
https://oss.connpass.com/event/129794
今は7月の終わりです。三ヶ月弱経ってから当時の資料を見直すと、もう何をやっていたのか思い出せません…。
そこで、記憶に定着させるために自分自身で記事を書いてみたいと思います。

適宜、勉強会で使用されたスライドを確認します。
https://kslides.page.link/2019-05-01_GitLv3
## 環境
MacBook Air (13-inch, 2017)
macOS Mojave 10.14.6
git version 2.21.0
Sourcetree Version 3.1.2(216)  ※コミットログの確認に使用します
## 準備
以下のコマンドを実行し、コミットを作成しておきます。

```bash
REPOS_NAME=repos35

cd
rm -rf $REPOS_NAME
mkdir $REPOS_NAME
cd $REPOS_NAME
git init
echo 1 > 1.txt && git add . && git commit -m "1"
echo 2 > 2.txt && git add . && git commit -m "2"
echo 3 > 3.txt && git add . && git commit -m "3"
echo 4 > 4.txt && git add . && git commit -m "4"
git checkout -b BranchX HEAD~~
echo A > A.txt && git add . && git commit -m "A"
echo B > B.txt && git add . && git commit -m "B"
git log --graph --all --oneline
````

作成後のコミットツリーをSourceTreeで確認すると、次のようになります。
![スクリーンショット 2019-07-28 19.34.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/df8c24c3-c4fa-d690-15a3-a6a785fa1f9e.png)
masterブランチの 2.txt が追加されたコミット。画像だと「e830b49」のコミットを起点とし、
masterブランチでは、「f27dd54」「01d1a9a」のコミットが、
BranchXブランチでは、「45f4255」「ea5e56c」のコミットが追加されています。

この準備作業は何度も行うので、コミットIDはそのたびに変わります。

以降では、コミットの説明にある、1, 2, 3, 4, A, Bで、コミットの識別をします。
## git rebase
git rebase -i　からできる操作をいくつか確認します。
### コミットの削除
準備
![スクリーンショット 2019-07-28 19.34.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/f9c14e8b-b9b7-d399-4bd1-860e183a8d04.png)
現在はBranchXのHEAD（コミットBの後ろ）にいます。
この状態からコミットAを削除するために、git rabase を使用します。
git rebaseには -i オプションをつけます。git rebase -i のあとに、コミット2のIDを指定します。

余談ですが、rabaseは「土台」という意味で、特定のコミットを土台にして作業することを意味するようです。
コミット2のIDを指定するのは、「コミット2を土台としてコミットを編集する」ことですね。

-i オプションは「--interactive」の略で、interactiveは「対話的」を意味します。
まとめると、「コミット2を土台としてコミットを編集する」を「対話的」に行う。ということでしょうか。

さて、本題に戻ります。

git rebase -i にコミット2のIDを指定します。コマンドにすると次のようになります。

````bash
git rebase -i e830b49
````

実行すると自動的にviが起動し次のような画面になります。
![スクリーンショット 2019-07-28 20.08.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/313d5060-ea0c-89c7-f73a-58b6869551ca.png)
この状態で1, 2行目の編集を行い、保存することでコミットの編集が可能になります。
コミットAを削除するために、1行目を削除し、保存します。
![スクリーンショット 2019-07-28 20.12.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/1f0d3ba3-5ab3-995c-a16b-4fb56b2be821.png)
ここまで操作したら、SourceTreeでコミットツリーを確認します。
![スクリーンショット 2019-07-28 20.13.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/c386b302-c64d-0c8f-5337-275dbfab2c7f.png)
コミットAが消えました。
作業コピーを確認すると、コミットAで追加したA.txtも削除されています。
![スクリーンショット 2019-07-28 20.16.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/add4da85-9af9-948c-c2e6-18dfeb05b470.png)

### コミットの順序入れ替え
準備のコマンドを実行し、コミットを再作成します。
![スクリーンショット 2019-07-29 00.38.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/f005831e-d037-11ec-6bfb-f9103c4f6b7d.png)

コミットAとコミットBを入れ替えます。
git rebase -i にコミット2のIDを指定します。

````bash
git rebase -i 2986ff9
````

viが起動します。
![スクリーンショット 2019-07-29 00.40.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/0fca2d61-f3e9-324d-ab1b-8aee7c888a1f.png)
コミットAとコミットBを入れ替えます。
viでの操作としては、コミットAの行で
dd
を入力し切り取り、
コミットBの行で
p
を入力し貼り付けます。
![スクリーンショット 2019-07-29 00.47.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/131d56d4-423e-4e32-753b-efdc2b00d63b.png)

保存し、SourceTreeのコミットツリーを確認すると、コミットAとコミットBの順序が入れ替わっています。
![スクリーンショット 2019-07-29 00.48.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/ec669862-ddea-4761-ec04-3bbfffe06798.png)

### コミットメッセージの変更
準備
![スクリーンショット 2019-07-29 20.41.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/f0391ab9-dd57-ad20-24de-badb1510462f.png)
過去のコミットメッセージを変更します。
git rebase -i にコミット2のIDを指定します。

````bash
git rebase -i 11d2af2
````

viが起動します。
![スクリーンショット 2019-07-29 20.47.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/799e194a-164b-604c-0a50-117a83bd342c.png)
コミットAのコミットメッセージを変更するために、コミットAの「pick」を「reword」に書き換え、保存します。
rewordは「書き換え」という意味です。
![スクリーンショット 2019-07-29 20.50.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/1ddd2301-0f67-8dba-5a7d-024ecb4b6826.png)
保存後にviを終了すると、コミットAのコミットメッセージ変更のために再度viが開かれます。
![スクリーンショット 2019-07-29 20.52.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/883a508d-a081-c3cc-a076-021fa2efdf8d.png)
コミットメッセージを変更し保存します。
![スクリーンショット 2019-07-29 20.53.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/aa06d649-680a-89a3-89eb-dc5f6072d9fb.png)
SourceTreeで確認すると、コミットAのコミットメッセージが変更されていることが確認できました。
![スクリーンショット 2019-07-29 20.54.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/14bdb9d3-918c-4270-3ea8-d3169849c684.png)

### コミット統合
準備
![スクリーンショット 2019-07-29 21.06.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/6e9a15c3-d83c-f36f-f0a0-c32297a06cd3.png)
コミットAとコミットBを一つにまとめます。
git rebase -i にコミット2のIDを指定します。

````bash
git rebase -i 9783485
````

viが起動します。
![スクリーンショット 2019-07-29 21.12.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/5a130a0f-874c-b307-54c8-a376e2b3f962.png)
コミットBの「pick」を「squash」に変更します。
squashは押しつぶすといった意味で、この指示によりコミットBで行った変更は、一つ前のコミットであるコミットAと一つにまとまります。
![スクリーンショット 2019-07-29 21.14.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/ba563212-439b-2347-85cd-73ce3f8418bd.png)
保存しviを終了すると、一つにまとめるコミットメッセージを編集するために再度viが起動します。
![スクリーンショット 2019-07-29 21.18.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/cc8d851b-6fb6-c6db-765f-60afb97ff78f.png)
コミットBのコミットメッセージを削除し、コミットAのコミットメッセージを変更してみました。
![スクリーンショット 2019-07-29 21.20.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/5700c6a2-c9e7-4f85-e15d-7f6e21eb3eb3.png)
SourceTreeで確認すると、コミットAとコミットBが一つになったコミットが作成されています。
![スクリーンショット 2019-07-29 21.21.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/b6cc762e-3643-166a-60df-220482ed0104.png)
変更内容にはコミットAとコミットBの両方の変更内容が含まれています。
![スクリーンショット 2019-07-29 21.23.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/075c0577-933e-7005-2ea3-e98b2dc4d578.png)

### 分岐元の変更
準備
![スクリーンショット 2019-07-29 22.57.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/cc347bf7-205e-d4b5-3010-dba7b79067ec.png)
いまBranchXはコミット2を分岐元としています。
これを、コミット4が分岐元となるように、分岐元のコミットを変更します。
git rebase masterを実行します。

````bash
git rebase master
````

SourceTreeで確認すると、BranchXの分岐元がコミット2からコミット4に変更されています。
この、「git rebase master」は、
ブランチを切ったあとにmasterブランチが更新された場合に使用されることが多いそうです。
コミットログが見やすくなりますし、マージの回数をへらすことが出来ます。
![スクリーンショット 2019-07-29 23.08.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298217/90d81cf7-997d-3eb0-23fe-73631d62a781.png)