ブランチを途中からリベースしたい

# はじめに

リベースは便利ですよね。
私はよくお世話になっています。

なんていうか、
`main`ブランチとか真っ直ぐな方が好きだな～なんてｗ

ほら、普通にマージしたりしていくと、
マージコミットが入って、2本が1本に合流する点ができて
その先にまた別のブランチが合流して・・・

あんまり綺麗に思えないというか・・・。

あと、コンフリクトが発生したときの解消が後回しっていうのが・・・。
問題は先に解決しておきたい派なので、なんだかなーなんて感じてしまいます。

とまぁ、私のような人だと分かってもらえると思うんですけど、
PRを投げて待っている間に実装進めておこうとかすると結構ブランチが直列になるんです。

そして、PRのapproveもらったらsquash mergeでfast-forward mergeして・・・
そうすると、直列先のブランチが残っちゃうんですね。

ここで<font color="#f00">**途中からリベースしたい**</font>という需要が生まれる訳です。

# 方法

いくつか方法はありますが、今回は`--onto`を使用したリベースを紹介します。

コマンドとしては、以下のようになります。

```bash:コマンド
$ git rebase --onto （移動先） （どこから） （どこまで）
```

と言っても、このままだと分かりづらいと思うので、
いくつかのパターンを具体例として、どういう動作をするのかを見ていきましょう。

## `git rebase --onto A B C`

このA、B、Cはブランチ名とします。

つまり、以下のような状態だと思ってください。

![image01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525820/db92332c-95ec-33cc-b08e-d1762e79f214.png)

そして、コマンドから読み解くと、以下のようになりますね。

![image02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525820/92ac09c4-51e3-4d2f-0dbc-f09bcc06f8ea.png)

これがコマンドを叩くことにより、以下の状態になります。

![image03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525820/656afb6c-d189-2444-e608-5c211d59803b.png)

ここで注意する点は、あくまで移動するのは<font color="#f00">**Bよりも先だけ**</font>ということです。
Bの最後のコミットは含まれません。

あくまでB（どこから）の指定は、基準に過ぎないということです。

## `git rebase --onto A hashB C`

先程と同様で、A、Cはブランチ名とします。
そして、先程とは異なり、hashBはコミットハッシュです。

<font color="#f00">**ブランチCを途中からAにリベースしたい**</font>けど、都合良くブランチがないって感じですね。

![image04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525820/5ce01b2c-f629-be82-932b-7186ec43e390.png)

もう動作は想像できると思いますが、以下のようになりますね！

![image05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525820/4fe2ed0b-21d3-b62f-c7ea-28b5c865aff9.png)

## 応用編

ここからは応用編です。

### `git rebase --onto A B B`

今回はA、Bをブランチ名として、2種類しか存在しません。
「どこから」と「どこまで」が一致しているという状態です。

![image06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525820/783d36c0-c0bc-04a8-abd1-fb7efdbafb45.png)

そして、思い出してほしいのは、
<font color="#f00">**「どこから」の指定は基準で、移動に含まれない**</font>ということです。

つまり、「Bより先で、Bまで」を移動することになるのですが、
結論から述べますと、<font color="#f00">**何も移動せず、ブランチだけ移動する**</font>ことになります。

![image07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525820/ced8817f-d95a-cd51-f6ac-6c20d70c0093.png)

ブランチ名だけを移動させたり、中身をリセットしたりする用途でも使えるかもしれませんね。


[【2022/02/24 9:44 追記 ここから】](https://qiita.com/mitashun/items/98ab98e83c0bba1ecba8#comment-ae00bb5f17af30216ee9)
~~ちなみに、以下のコマンドも同様の操作になります。~~
ちなみに、<font color="#f00">**Bのブランチをチェックアウトしている状態であれば**</font>、以下のコマンドでも同様の操作になります。

```bash:この指定でも同じ操作（Bのブランチをチェックアウトしている状態であれば・・・）
$ git rebase --onto A B
```

~~「どこから」と「どこまで」が一致しているので<font color="#f00">**省略可能**</font>ということですね。~~

これに関しては、誤りでした！！
申し訳ございません！！

操作的には、
`git rebase --onto A B`は、`git rebase --onto A B head`の操作になるため、
Bのブランチをチェックアウトしていない状態だと想定外の動作をして、あなたを混乱させる原因になるところでした！

指定が省略できるからって簡単に省略してはダメですね・・・。

また、

> めちゃくちゃになってしまったブランチを元の状態に戻したいなら、リベース前のコミットIDをメモしておいて`git reset --hard 《リベース前のコミットID》`を実行しましょう。

というコメントを頂いております。

まだまだ発展途上であることも承知の上での記事作成なので、
こうして誤りを指摘していただけることがありがたい限りです。

今後も自身の知識をアップデートしながら、成長のため**誤った内容**の記事をまとめることがあるかもしれませんが、
そのときは是非とも「間違ってるよ」って教えていただけると幸いです。

[【2022/02/24 9:44 追記 ここまで】](https://qiita.com/mitashun/items/98ab98e83c0bba1ecba8#comment-ae00bb5f17af30216ee9)

# コンフリクトの解消

基本はリベースしたときの解消方法と同様です。

コンフリクトが起きた時点で、リベースが止まりますので、
コンフリクトを解消するためにコードを修正しましょう。

コンフリクトが解消できましたら、
SourceTreeなどを使用しているのであれば、忘れずにステージし、
コマンドであれば、忘れず`git add`しましょう。

その後に、
`git rebase --continue`でリベースを再開する、
という手順ですね。

# 注意点

もう分かってるよ！っていう方もいると思いますが、念のため・・・。

## プッシュする前のリベース作業

元に戻すのが困難になるのでお勧めしません。

プッシュしておけば、
万が一リベースをミスしてもローカルのブランチを破棄して、
リモートからブランチを切ることで簡単に元の状態に戻せます。

<font color="#f00">**プッシュしてからリベース作業は行うようにしましょう。**</font>

## 強制プッシュ

リベースには強制プッシュが付き物ですね。

強制プッシュは簡単にできてしまいますが、
<font color="#f00">**破壊的な操作**</font>であることを忘れずに
慎重に操作するようにしましょう。

特に、`--force-with-lease`をつけて、
比較的安全に強制プッシュができるようにするのは当然の配慮ですよ！

## 「どこから」の指定をミスする

慣れない内はやってしまいがちかもしれません。
そのため、<font color="#f00">**プッシュしてからリベース作業を行う**</font>ことは重要になります。

「どこから」で指定したコミットは移動に含まれませんので、
<font color="#f00">**移動させたい最初のコミットの1つ前のコミット**</font>を指定しましょう。

# さいごに

少しまとめてみましたが、いかがでしょう。
参考になれば嬉しいです。

ただリベースもコンフリクトも非常にシビアなので、
困ったときは先輩・上司を巻き込むことをお勧めします！