git rebase を日本一わかりやすく解説する - 利点編
この記事は何
git rebase
について解説します。
rebase
のことをあまり知らない以上、git のことも細かいコマンドはあまり知らない方が多いと思います。git の知識はそこまで要りません。 git でチーム開発でも個人開発でも何かしら経験あれば十分 OK です。
git rebase
について、日本語で一番わかりやすく解説します。
rebase の噂
rebase についてあまり知らない人が rebase に対して聞いたことある噂はこんなところじゃないでしょうか
-
git merge
に似た何からしい - git の履歴が綺麗になるらしい
- git の履歴を改竄するらしい
- rebase を嫌うエンジニアも少なく無いらしい
- 事故りやすいらしい
「rebase を嫌うエンジニアも少なく無いらしい」ので、嫌いになっても仕方がないです。
が、理解してから嫌いになりましょう。
汚い
コミット履歴とは
噂の
git の履歴が綺麗になるらしい
について、そもそも コミット履歴が汚い
とは何かを定義しましょう。
まずは1つのブランチだけに着目する
ロボットの組み立て作業を feat/robot
ブランチで行いましょう。
汚いコミット履歴 | 綺麗なコミット履歴 |
---|---|
![]() |
![]() |
もちろん、最終的な成果物となるコードは同じです。
人によっては 汚いコミット履歴
も別に普通じゃない?と思う人も多いでしょう。
ただこの2つを比べたとき、「どちらが綺麗か」と問われれば、ほとんどの人は右と答えるでしょう。
このことから、綺麗なコミット履歴
とは
-
WIP := 作業中
のコミットが少ないこと -
fix := 不具合修正
のコミットが少ないこと -
feat := 機能追加
のコミットの割合が多いこと - 1つの機能追加が1つの
feat
コミットに対応していること
と言えるでしょう。
コミット履歴が綺麗なことで、
- レビューのしやすさ
- 開発履歴の追いやすさ
が期待できます。
複数のブランチが関わるときを考える
先ほどは 1つだけのブランチでしたが、チーム開発をする以上、複数のブランチが入り組みます。
同様に、汚いコミット履歴
と 綺麗なコミット履歴
を見てみましょう。
汚いコミット履歴 | 綺麗なコミット履歴 |
---|---|
![]() |
![]() |
(若干違うところがありますが、気にしないで...🙏)
これはさすがに満場一致で「どちらが綺麗か」と問われれば、右と答えるでしょう。
このことから、綺麗なコミット履歴
とは
- ブランチのネストが少ないこと (main -> branchA -> branchB といった具合に、作業ブランチから作業ブランチを生やすこと)
- 作業ブランチ間でマージが少ないこと
- main から作業ブランチへのマージが少ないこと
rebase が輝くケース
rebase を使って運用する場合、主に用いる rebase の機能はざっくり 2つです
-
-i
のインタラクティブモードを用いて、あるブランチのコミット履歴を改竄する - 作業ブランチの分岐元コミットを変更する
1. 作業ブランチ単体を綺麗にする
再掲
汚いコミット履歴 | 綺麗なコミット履歴 |
---|---|
![]() |
![]() |
rebase を用いると、左の 汚いコミット履歴
を右の 綺麗なコミット履歴
へと改竄します。
改竄と聞くと印象悪いですが、コミット履歴を「お掃除」するわけです。
どう「お掃除するか」、下図のように
- ある機能のための WIP コミットは、ある機能が完成したコミットにまとめる
- 下図の同じ色のコミットは、1つのコミットへまとめる.
- ある機能に対する fix コミットは、ある機能が完成したコミットにまとめる
- その機能を実装した特定のコミットへまとめる.
とします。
「お掃除」前 | 「お掃除」後 |
---|---|
![]() |
![]() |
この「お掃除」が、git rebase を使うことで可能です。
具体的な方法は、他の解説記事に丸投げします💦
この記事では
- rebase でできること
を理解することを目標にします。
2. 入り乱れたマージコミットを発生させない
汚いコミット履歴 | 綺麗なコミット履歴 |
---|---|
![]() |
![]() |
上記、結果的なソースコードは同じですが、綺麗なコミット履歴
の方がやはり見通しがいいですし、開発の過程がわかりやすいですよね
汚いコミット履歴
が 汚い
たる所以は
-
feature2
branch が、main の変更取り込みマージコミットを行っている -
feature3
branch が、main の変更取り込みマージコミットを行っている
点です。
rebase を知らない人からしたら、「そんなのどうしようもなくね」となりそうですが、どうしようもあるんです。
あなたが feature2
で開発をしている人だとして、綺麗なコミット履歴を目指そうとしたら、こういう欲がでませんか
-
feature1
の main へのマージがもう少し早ければ... -
feature1
が main へマージされてからfeature2
ブランチをはやせていれば...
という欲望を rebase
で実現可能です。
下記の状態では、
-
feature1
ブランチがmain
にマージされるよりも前のmain
からfeature2
branch をはやしている
という状態ですが、これを
-
feature1
ブランチがmain
にマージされたコミットから branch をはやしている
にします。
git checkout feature2
git rebase main
結果
実行前 | 実行後 |
---|---|
![]() |
![]() |
これにより
-
feature1
がmain
にマージされたコミットからあたかもfeature2
ブランチが生えた
ように変更できます。歴史を改竄しています。
ここで、ついでに feature3
も rebase してみます
実行前 | feature2 rebase 後 | さらに feature3 rebase 後 |
---|---|---|
![]() |
![]() |
![]() |
これにより、 汚いコミット履歴
の要因であった
feature2
branch が、main の変更取り込みマージコミットを行っているfeature3
branch が、main の変更取り込みマージコミットを行っている
を取り除くことができました。
欠点
利点のみをお話ししましたが、欠点も存在します。
歴史を改竄するということは、その git 履歴を誰かと共有する際に整合性があわなくなります。
そのため公式でも述べられているのが
公開リポジトリにプッシュしたコミットをリベースしてはいけない
という点です。
local にある git を remote に接続している場合、その branch は誰かと共有していることになります。
開発の一般的ルールとして、ある branch の作業者は原則一人なので問題ないですが、main
や develop
などを rebase するのは言語道断となります。
時間があったら 『git rebase を日本一わかりやすく解説する - 欠点編』を記述したいとおもいます。
まとめ
冒頭に書いた下記の噂
git merge
に似た何からしい- git の履歴が綺麗になるらしい
- git の履歴を改竄するらしい
- rebase を嫌うエンジニアも少なく無いらしい
- 事故りやすいらしい
を理解できたのではないでしょうか
rebase は便利でもあり、危険な側面も含んでいます。
まずは rebase のことを知り、その後プロジェクトでどのように運用するかを決めていきましょう。
Discussion