はじめに
こんにちは、クレイの亀井です。ここ最近一気に気温が上がりましたね。顔に重点的に汗をかくタイプの私には憂鬱な季節がやってまいりました😩💦
さて、今月正式リリースしました(!) DocBase プロジェクトではクレイ外部のデザイナーの方と一緒に開発しています。SourceTree で Git を使っている方で、軽いデザイン修正などは弊社の Rails プロジェクトに直接手を加えてプルリクエストを送ってくれます。
こちらのデザイナーさんに「プルリクエストを送る際は、作業ブランチで git pull --rebase origin master してから送ってもらえますか?」とお願いすると「pull はわかるんですけど、この --rebase ってなんですか?これつけると何が変わるんですか?」と質問がきたのです。
作業ブランチで git pull --rebase origin master してほしい理由はなるべく最新の master に近い状態でプルリクエストを送ってほしいからなのですが、デザイナーさんは作業ブランチに最新の master を取り込むのに git pull origin master を使っていました。
なぜ git pull --rebase する必要があるのか、改めて説明しようとするととても難しく、口頭では説明しきれなくて自分自身の力不足を感じました。。
もっと段階を踏んで理解する必要がある
業務の中で Git のことが理解できるようになってからわかったことですが、git pull --rebase を理解するには、なんとfetch、merge、rebase の3つの Git コマンドをちゃんと理解する必要があります。ヒャー!
この記事では図を交えながら、感覚的に理解できることを目指して説明していきたいと思います。
長くなりますが、ファイトです!
さっそく説明といきたいところですが!今後の説明に使うので、まずはローカルリポジトリとリモートリポジトリについてさらっとおさらいします。
ローカルリポジトリとリモートリポジトリ
Git にはローカルリポジトリとリモートリポジトリという2種類のリポジトリがあります。ローカルリポジトリは作業者のPCにあるリポジトリ、リモートリポジトリは共用のサーバに設置されているリポジトリです。
ローカルリポジトリで作業して、適宜リモートリポジトリにプッシュするというのがGitを使った開発の大まかな流れになります。
Git のローカルリポジトリには
* ワーキングツリー
* インデックス
* ローカルブランチ
* リモート追跡ブランチ
があります。
ローカルリポジトリの中に「リモート追跡ブランチ」というのがいますが、これはリモートリポジトリのコピーです。これだけ言われてもなんのこっちゃと思う方もいらっしゃるかもしれませんが、これからの説明の肝になるので注意しておいてください!
ではではざっくり Git の構造を図にしたところで、fetch、merge、rebase、pull & pull --rebase の説明をしていきたいと思います。
git fetch とは
git fetch とは「リモートのコピーをローカルにダウンロードする」コマンドです。ローカルのリモート追跡ブランチ(リモートのコピー置き場)にコピーしてくるだけなのでワーキングツリーには何も影響を及ぼしません。
git fetch
上記のコマンドを実行した場合の動きを、図に表してみます。
- リモートのコピーちょうだいって言う
- ローカルとの差分を見つつ、リモートリポジトリが変更や新規ブランチをリモート追跡ブランチに渡す
- リモート追跡ブランチが更新される
ちなみにこの「リモート追跡ブランチ」とはあくまでリモートの状態を示すもので、ユーザー自身がこのブランチの内容を変更することはできません。(内容を見たりとかはできます)また、リモートの状態は自動的に反映されるわけではなく、git fetchコマンドで明示的に行う必要があります。※SourceTreeには自動フェッチ機能があるそうです。(使ったことないのであまりよくは知らないです、すみません)
このリモート追跡ブランチの内容を見たり、ローカルブランチにマージしたりするときは
git merge origin/master
というふうに、origin/ブランチ名 の形でアクセスできます。
git merge とは
git merge とは、今いるブランチに別のブランチの内容を結合させるコマンドです。リモートリポジトリにあるブランチや、ローカルの別のブランチをマージしたいときに使います。
ローカルブランチがこんなかんじであるとしまして(master や hige はブランチ名です)
hige ブランチに master ブランチの内容をマージしたいときは、以下のコマンドを使います。
git checkout hige // 現在higeブランチにいるなら不要
git merge master
これで hige ブランチの中に master ブランチの内容が取り込まれます。また、マージした場合は「マージコミット」というコミットが積まれます。
また、マージには Fast-Forword と Non-Fast-Forword という2種類のマージがありますが、ここでは割愛します。わかりやすく解説してくださっている方がいるので、そちらを参照してください。
【git】分かりやすく!mergeは「合流」、rebaseは「付け替え」!
リモートリポジトリのブランチをマージする場合
ちなみに、上記のコマンドはローカルリポジトリの master ブランチをマージするものなので、リモートの master ブランチをマージするには以下のコマンドを実行します。
git fetch // 先にリモートの状態をリモート追跡ブランチにコピー
git merge origin/master // リモートのコピーからマージ
まず git fetch でリモートにリモート追跡ブランチを合わせたあと、
git merge origin/master で master に origin/master の差分が取り込まれます。
origin/ブランチ名 はリモート追跡ブランチのことでしたね。(fetch のセクション参照)git merge コマンドでリモートのブランチをマージしたい場合は、いったんリモートのコピーをとってきて、そのコピーをマージするという手順になります。
git rebase とは
git rebase とは、merge と同じく今いるブランチに別のブランチの内容を取り込むコマンドですが、merge とは動きが違います。
前提は、git merge の時と同じこちらの状態です。
この状態で、hige ブランチを master にリベースしたい場合、以下のようになります。
git checkout hige // higeブランチにいるなら不要
git rebase master
まず、hige ブランチにあるふたつのコミットを一時的に保存、hige ブランチをリベース先のブランチに git reset --hard します。
リセット後の hige ブランチの上に一時保存していたコミットを乗せます。
hige ブランチの猫には口がなかったのに、リベース後は口がついてますね。差分がコンフリクトしていなければ Git がうまいことくっつけてくれます。(コンフリクトしたときはエディタを開いて手動で直しましょう。。。)
ただ、マージと違ってリベースの場合はコミットを新しく作りなおすので、リベース前とはコミット自身の id と親の id が変わります。master の変更を取り込んで別物になったので当然ですね。
親のidが変わると、すでにリモートリポジトリにブランチをプッシュしていた場合、リモートにあるブランチの親の id が一致せずプッシュできなくなり(rejectされ)ます。(git push -f で強制的にプッシュできますが、よくわかっていないうちは使わないほうがいいでしょう。)
マージは現在のブランチの上に他のブランチの内容を取り込むというかんじですが、リベースは取り込みたいブランチの上に今のブランチの内容を乗せるといったかんじですね。
git pull とは
git pull とは、さきほど説明したgit fetch と git merge をいっぺんに実行するコマンドのことです。
git merge のセクションで言っていた以下のコマンド。
git fetch // 先にリモートの状態をリモート追跡ブランチにコピー
git merge origin/master // リモートのコピーからマージ
こちらのコマンドは、
git pull origin master
とイコールです。フェッチしてからマージするのMENDOIと思うようになったら使いどきです。
git pull --rebase とは
ついにお待ちかねの git pull --rebase です。
--rebase は git pull コマンドのオプションです。git pull は fetch + merge ですが、--rebase オプションをつけると fetch + rebaseとして実行します。
git pull --rebase origin master
git pull と git pull --rebase の違い
冒頭で以下の様なやりとりをデザイナーさんとしていますが、
「ブランチを git pull --rebase origin master してからプルリクエストを送ってもらえますか?」
なぜこのようなお願いをしたかといいますと、--rebase オプションをつけてプルしたほうがマージコミットが作られない&履歴が綺麗になるからです。
このときに --rebase オプションをつけなくても「作業ブランチに最新の master を取り込む」という目的は達成できるのですが、上記の理由があるため作業ブランチに master を取り込むときは git pull --rebase でお願いしていました。
ただこちらはいろいろ議論がありまして、(「ログが綺麗になるとしても履歴を書き換えるべきではない」など)いきなりリベースをするとチームの規約に反する場合もありますので、そのあたりは事前にチームの人に確認してください。
また、マージするのに比べてリベースするほうが差分がコンフリクトしたときに修正するのが面倒なときがあったりするので、あまり Git に慣れていないうちは git merge でリモートリポジトリの差分を取り込むほうがいいかもしれません。
最後に
git pull と git pull --rebase の違いを説明するだけなのに、なんだかとても長くなってしまいました。そして、書くのに時間がかかりすぎて冒頭で質問してくれたデザイナーさんはすでに DocBase チームから離れていました。。。Kさん、見ていらっしゃいますでしょうか…?
Git はコミットさえしていれば間違えてコミットやブランチを消してしまっても元に戻せる方法があるので、テスト用のブランチを切って試してみるのもいいかもしれません💪元に戻しやすいのは Git のいいところのひとつですね!
ここまで読んでくださった方、ありがとうございました!この記事を読んで Git の理解が少しでも進めば幸いです。
宣伝
クレイでは情報共有サービスDocBase を開発しています。
- 最大10人までの同時編集に対応!
- 細かい権限設定でオープンな情報もクローズドな情報もDocBaseに一本化
- SSO、2段階認証、IPアドレス制限に対応。ISMSも取得しており、セキュリティには力を入れています!
チームを作成して30日間は無料ですべての機能が使えるので、ぜひチームを作成して試してみてください。
このエントリーに対するコメント
日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)
- トラックバック
-
- Git rebase merge の違い | hacknote2016/05/17, 6:44 PM
[…] したいと思います。 rebaseとmergeの違い […]
-
- 【Git】マージコミットを消したい – RE:ENGINES2017/08/21, 8:04 AM
[…] きず、綺麗にリモートを取り込めます。 git pullとgit pull –rebaseの違いはこちらのサイトで分かりやすく紹介されております。 git pull と git pull –rebase の違いって?図を交えて説明します! […]
-
- 【Git編】テックキャンプエキスパートで教えてくれなかったこと | とむじそブログ2017/10/12, 3:23 AM
[…] git pull と git pull –rebase の違いって?図を交えて説明します! https://kray.jp/blog/git-pull-rebase/ […]
-
- コマンドラインでGitを使うようになったので色々メモ - 3000 Leagues in Search of Russia2017/11/23, 12:56 PM
[…] 『git pull と git pull –rebase の違いって?図を交えて説明します!』 (https://kray.jp/blog/git-pull-rebase/) […]
-
- まずはGitの仕組みを理解することから | IT技術情報局2018/01/02, 6:56 PM
[…] 参考:git pull と git pull –rebase の違いって?図を交えて説明します! […]
-
- Gitの説明しつつ、OneDriveとVisual Studio Codeの環境を作る – 10bace LOG2018/01/11, 6:34 PM
[…] ⇒意味とか […]
-
- WebデザイナーがGitを始めて大変だった・めっちゃ良かった話2018/01/26, 8:35 AM
[…] git pull と git pull –rebase の違いって?図を交えて説明します! ちょっと上級者向け?ですが、ブランチ運用の概念についての図解がわかりやすくて良かったです。猫が可愛い。 […]
-
- Git入門(VSCode Git の使い方) – セルティスラボ2018/04/18, 4:06 PM
[…] git pull と git pull –rebase の違いって?図を交えて説明します! […]
-
- Rails歴1年未満・10代のひよっこがRailsにプルリク出してみた話 | IT技術情報局2018/06/11, 12:51 AM
[…] ては、この記事がわかりやすかったので参考にしてください。 git pull と git pull –rebase の違いって?図を交えて説明します! 大事なことは、マージコミットをrailsのコミットログに残さな […]
-
- いまさらだけどGitを基本からまとめてみた | IT技術情報局2018/08/11, 12:50 PM
[…] ブランチモデル rebase pull […]
-
- いまさらだけどGitを基本から分かりやすくまとめてみた | IT技術情報局2018/08/14, 8:50 AM
[…] ブランチモデルに関して rebaseに関して pullに関して […]
-
- "git pull origin master" の正体 | IT技術情報局2018/08/17, 11:51 AM
[…] こちらの記事がとてもわかりやすくローカルリポジトリがリモートについてまとめておられたので、これをみて自分の頭を整理するついでに”git pull origin master”は何をしているの […]
-
- 入社して1年間でよく使ったGitコマンドまとめ | とむじそブログ2018/11/10, 10:04 PM
[…] git pull と git pull –rebase の違いって?図を交えて説明します!/ KRAY […]
「いいね!」で応援よろしくお願いします!