見出し画像

GitHub_mergeとrebaseの違いを理解する #237日目

Gitでブランチを統合する方法のうち、mergeとrebaseの違いについて整理したいと思います。

まず簡単に違いを書くと以下の通りです
merge:
コミット履歴をそのまま残して統合(ブランチB→Aへのmerge)
rebase:
統合先のブランチでコミットされたように履歴が残る(ブランチB→AへrebaseするとそのコミットはブランチA内で行われたように残る)


自分の作業内容をコミットしてプッシュする場合は、基本的にはmergeを使うことになると思います。rebaseを使う場面としては、①コミット履歴をシンプルにしたい場合や、②トピックブランチ(作業ブランチ) に統合ブランチ (mainやmasterブランチ) の最新の内容を反映させたい場合などです。

分かりやすい図があったので引用させていただきます。
トピックブランチを統合ブランチに普通にmergeしているのが以下です。

トピックブランチを統合ブランチにmerge

次にrebaseを見てみます。rebaseではコミットの履歴が1つのブランチに統合されるので、履歴がシンプルになります。

https://backlog.com/ja/git-tutorial/stepup/04/


では、以下で具体的な動きを確認してみたいと思います。以前の記事で、Gitのコミット履歴を確認する方法を紹介しましたが、この方法を使って色々と確認していきます。

以下のようにブランチを派生させています。

main
     `- cd
          `- cd2

まず、ローカルで2つコミットした状態のcd2ブランチでログを確認します。

$ git checkout cd2
$ git log --graph --oneline 


* 9c11f00 (HEAD -> cd2, origin/cd2) seconde cd2cd2cd2 コミット
* 39854cb first cd2cd2cd2 コミット
* a4c67c0 Add space in COPY
* db5586f Change the version of uses in steps

普通にブランチのログが出てきました。

このcd2ブランチをcdブランチにrebaseしてみます。GitHub上で以下のようにプルリクエストできます。

ここでcdブランチのログを確認します。rebaseしているので、あたかもcdブランチでずっとコミットが行われてきたかのようになっています。

$ git checkout cd 
$ git log --graph --oneline


* befa2f0 (HEAD -> cd, origin/cd) seconde cd2cd2cd2 コミット
* 61d8738 first cd2cd2cd2 コミット
* a4c67c0 Add space in COPY
* db5586f Change the version of uses in steps


cdブランチをマージする前に、mainブランチのログを確認します。mainブランチは独自に更新していて、「!!!!!!!!!」という文字列を追加したというコミットが最新になっています。

$ git checkout main
$ git log --graph --oneline
 
 
* e83a5b9 (HEAD -> main, origin/main, origin/HEAD) add "!!!!!!!!" in title
*   49dc1e5 Merge pull request #5 from YM202110/cd
|\
| * a4c67c0 Add space in COPY
* | e31e4ad Merge pull request #4 from YM202110/cd
|\|
| * db5586f Change the version of uses in steps
* | b645af9 Merge pull request #3 from YM202110/cd
|\|


cdブランチをmainブランチにマージしたら、mainブランチのログを確認します。「cd2cd2cd2」とつくコミットは、実際はcd2ブランチで行ったものですが、cdブランチにrebaseしているので、cdブランチで行われたように見えています。

$ git checkout main
$ git log --graph --oneline


*   ac4ef50 (HEAD -> main, origin/main, origin/HEAD) Merge pull request #7 from YM202110/cd
|\
| * befa2f0 (origin/cd, cd) seconde cd2cd2cd2 コミット
| * 61d8738 first cd2cd2cd2 コミット
* | e83a5b9 add "!!!!!!!!" in title
* | 49dc1e5 Merge pull request #5 from YM202110/cd
|\|
| * a4c67c0 Add space in COPY
* | e31e4ad Merge pull request #4 from YM202110/cd
|\|
| * db5586f Change the version of uses in steps
* | b645af9 Merge pull request #3 from YM202110/cd
|\|


次はrebaseではなくmergeだとどうなるか見ていきます。
main→cd_new→cd2_newとブランチを作り、cd2_newでの変更をcd_newへmergeした後のログが以下です。mergeだと履歴がありのままに残るので、cd2_newブランチでコミットした様子が残っています。

$ git checkout cd_new
& git log --graph --oneline
 
 
*   ac4ef50 (HEAD -> cd_new, origin/main, origin/cd_new, origin/HEAD, main) Merge pull request #7 from YM202110/cd
|\
| * befa2f0 (origin/cd2_again, origin/cd) seconde cd2cd2cd2 コミット
| * 61d8738 first cd2cd2cd2 コミット
* | e83a5b9 add "!!!!!!!!" in title
* | 49dc1e5 Merge pull request #5 from YM202110/cd
|\|
| * a4c67c0 Add space in COPY
* | e31e4ad Merge pull request #4 from YM202110/cd
|\|

この後、cd_newからmainブランチにmergeすると以下のようなログになります。

$ git checkout main
& git log --graph --oneline

 

*   9a69087 (HEAD -> main, origin/main, origin/HEAD) Merge pull request #10 from YM202110/cd_new
|\
| * 029b9fa (origin/cd_new) Merge pull request #9 from YM202110/cd2_new
|/|
| * 48b758a (origin/cd2_new, cd2_new) cd2_new!を追加
|/
*   ac4ef50 (cd_new) Merge pull request #7 from YM202110/cd
|\
| * befa2f0 (origin/cd2_again, origin/cd) seconde cd2cd2cd2 コミット
| * 61d8738 first cd2cd2cd2 コミット
* | e83a5b9 add "!!!!!!!!" in title
* | 49dc1e5 Merge pull request #5 from YM202110/cd

少し分かりにくいので詳細を表示してみます。

$ git checkout main
& git log --graph --oneline
 
 
*   commit 9a690879870f46ca2870f89a9f72a287a7e51de7 (HEAD -> main, origin/main, origin/HEAD)
|\  Merge: ac4ef50 029b9fa
| | Author: もり <96642466+YM202110@users.noreply.github.com>
| | Date:   Sun Aug 7 11:10:07 2022 +0900
| |
| |     Merge pull request #10 from YM202110/cd_new
| |
| |     cd2_newからコミットしてきた内容をcd_newからmainにマージ
| |
| * commit 029b9fab8de3166e56b075847a74e3b4eb002a8b (origin/cd_new)
|/| Merge: ac4ef50 48b758a
| | Author: もり <96642466+YM202110@users.noreply.github.com>
| | Date:   Sun Aug 7 11:03:50 2022 +0900
| |
| |     Merge pull request #9 from YM202110/cd2_new
| |
| |     cd2_new!をcd_newにマージ
| |
| * commit 48b758adc427d3263ad6b06ad8c6910fdca66018 (origin/cd2_new, cd2_new)
|/  Author: y.mori <a.m.h.yu90@gmail.com>
|   Date:   Sun Aug 7 11:01:12 2022 +0900
|
|       cd2_new!を追加
|
*   commit ac4ef50fac9c25ee6d4677a6c74e922e4cb9941a (cd_new)
|\  Merge: e83a5b9 befa2f0
| | Author: もり <96642466+YM202110@users.noreply.github.com>
| | Date:   Sun Aug 7 10:37:48 2022 +0900
| |
| |     Merge pull request #7 from YM202110/cd
| |
| |     cdブランチにリベースしたcd2ブランチでのコミット内容の反映
| |


上記の通り、rebaseだとコミット履歴が統合されてシンプルに管理することができますが、履歴を書き換えていることにもなるので、共同開発ではトピックブランチから統合ブランチへのrebaseは原則行いません(統合ブランチからトピックブランチへのrebaseはありそうですが)。

mergeだと全ての履歴が残るので基本はmergeが良いと思いますが、共同作業者が増えると履歴が複雑になるのでその点で注意が必要です。


ここまでお読みいただきありがとうございました!!

参考


この記事が気に入ったらサポートをしてみませんか?