LoginSignup
1
0

More than 3 years have passed since last update.

Gitのマージ、リベース再学習メモ

Last updated at Posted at 2020-10-28

散々記事として書かれている内容ですが Git におけるマージ、リベース関連の話です。
車輪の再発明な感じはしますが、ツール操作の再学習もかねて試したのでそのメモとして残します。

お断り。
コマンドのサンプル以外では、マージ、リベースのようにカタカナで記載しています。

準備

初期状態

履歴のイメージ。
pic01.drawio.png

補足
矢印の方向が上記のよう描いているのは、各コミットは親のコミット ID を持っているからです。

topic ブランチ作成

git branch topic

履歴のイメージ。この時点では、main ブランチ、topic ブランチ共に C2 を指している。
pic02.drawio.png

main ブランチでコミット

履歴のイメージ。main ブランチは C3 を指している。
pic03.drawio.png

topic ブランチでコミット

履歴のイメージ。topic ブランチは C4 を指している。
pic04.drawio.png
アプリでの見え方。GitKrakenでは main ブランチが枝分かれしたように見えますが、この辺はツール依存です。

GitKraken Fork
pic04k.png pic04f.png

いったん、マージする前の準備ができました。

変更を取り込む

topic ブランチ作成後に main ブランチが変更されています。複数人で共同開発している場合、変更内容を topic ブランチに取り込んでテストし、main ブランチにマージします。

ここでは2種類の方法を記載します。

topic ブランチをリベースする

C2 から topic ブランチを作成しましたが、これを C3 から topic ブランチを作成したようにするのがリベースです。

git checkout topic
git rebase main

# もしくは
git rebase main topic

履歴のイメージ。
pic06.drawio.png

この絵では枝分かれしたよう描いていますが、実際は一直線に並ぶイメージです。
説明はじめの方で main ブランチで C3 を作成したときに似ています。
pic07.drawio.png

リベース前後の履歴イメージ比較。コミット C4 の親が C2 から C3 に替わりました。

リベース前 リベース後
pic04.drawio.png pic07.drawio.png

アプリでの見え方。

GitKraken Fork
pic07k.png pic07f.png

これをマージするとどうなるでしょう。

チェリーピックで変更内容を取り込む

他のブランチの特定のコミットだけを取り込む仕組みがチェリーピックです。

履歴のイメージ。新しいコミットが作成されますが、変更内容は C3 と同じ。
pic102.drawio.png

アプリでの見え方。画像内の C3 などはコミットコメントで、コメントもそのまま新しいコミットとして作成されていることが分かります。

GitKraken Fork
pic10k.png pic10f.png

これをマージするとどうなるでしょう。

マージする

変更取り込み有無やマージの方法で履歴がどう変わるでしょうか。

変更を取り込まずにマージする

通常テスト後にマージするため、topic ブランチに変更を反映しないことはないと思いますが、直接マージできるケースの例です。

git checkout main
git merge topic

履歴のイメージ。main ブランチはマージによって新しいコミット C5 となります。
pic05.drawio.png

マージ前後の履歴イメージの比較。

マージ前 マージ後
pic04.drawio.png pic05.drawio.png

アプリでの見え方。

GitKraken Fork
pic05k.png pic05k2.png

リベース後にファストフォワードなしでマージする

通常 Git はファストフォワードありでマージしようとするのですが、先にファストフォワードなしの例を示します。

topic ブランチを main ブランチに対してマージする際、 --no-ff オプションを付けるとファストフォワードなしのマージとなり、コミットを作成してくれます。

git checkout main
git merge --no-ff topic

履歴のイメージ。C3 から分岐した C4C5 としてマージされます。

pic08.drawio.png
マージ前後の履歴イメージの比較。

マージ前 マージ後
pic07.drawio.png pic08.drawio.png

アプリでの見え方。

GitKraken Fork
pic08k.png pic08f.png

リベース有無によるForkの履歴の見え方を比較してみます。

リベースなし リベースあり
pic05k2.png pic08f.png

リベース後にファストフォワードありでマージする

こちらが Git デフォルトの動作です。

先ほどとは異なり --no-ff オプションを付けなかった場合、main ブランチにはコミットは作成されず、指し示すコミットだけが変更されます。

git checkout main
git merge topic

履歴のイメージ。
pic09.drawio.png

main ブランチが指し示すコミットを先に進めるだけの処理が「ファストフォワード(早送り)」となります。
マージ前後の履歴イメージの比較。

マージ前 マージ後
pic07.drawio.png pic09.drawio.png

アプリでの見え方。

GitKraken Fork
pic09k.png pic09f.png

アプリでも履歴のイメージ図のような見え方になっています。

マージ前 マージ後
pic07f.png pic09f.png

ご覧の通り、topic ブランチで作成した痕跡が残らないため、私はリベースするなら --no-ff オプションを付ける運用にしています。

チェリーピック後にマージする

最後に、チェリーピックを行ったときのマージです。

履歴のイメージは、ごく普通に新しいコミット C6 が作成されてマージされたものとなります。
pic11.drawio.png

チェリーピックしたときにコンフリクトが発生していなければ、コミット C6 の変更内容はコミット C4 と同じになります。これはコミット C3C5 は変更内容が同じのためです。

アプリでの見え方。

GitKraken Fork
pic11k.png pic11f.png

補足:プルとマージ

今回はあえて触れなかったリモートとの連携に関して少しだけ触れておきます。

他人の更新は基本的にリモートにあるためそれをローカルへ取り込む必要があります。
この方法としてはプルとフェッチがあります。
フェッチはリポジトリーの情報をローカルへ持ってくるだけ。プルはフェッチを行った後、ローカルブランチに対するマージを行う操作になります。

今まで記載してきたリベースやマージの部分を理解すると、プル操作にあるオプションが少しは理解しやすいのではないでしょうか。

・オプションなし:可能な限りファストフォワードをします。ファストフォワードできない場合はコミットを作成してマージします。--ff オプションと同じ。
--no-ff:リモートの変更を必ずコミットを作成してマージします。
--rebase:リモートの変更をリベースして取り込み、ローカルで変更した内容を反映します。
--squash:リモートの複数の変更をまとめてチェリーピックするような挙動をします。マージ済みの扱いになりますが、自動的なコミットは行われません。

最後に

コンフリクトが発生してない単純なケースでのまとめのため、実際はもっと複雑です。大人数で開発していると、裏ではどんどんマージが行われ、チェリーピックに追われる日々みたいなこともあります。

みんなで共有しているブランチでリベースだけはやめましょう:sob:

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0