Git リベース: 知っておくべきことすべて

公開: 2022-12-15
Linux コマンド プロンプトを表示している青色の背景のラップトップ。
Fatmawati achmad zaenuri/Shutterstock.com
Git rebase コマンドは、ブランチを別のブランチの先頭にある新しい場所に移動します。 Git のマージ コマンドとは異なり、リベースにはプロジェクト履歴の書き換えが含まれます。 これは素晴らしいツールですが、他の開発者が作業のベースにしているコミットをリベースしないでください。

Git rebaseコマンドは、2 つのソース コード ブランチを 1 つに結合します。 Git mergeコマンドもそれを行います。 rebaseの機能、使用方法、および代わりにmergeを使用する場合について説明します。

目次

Git 爆発
Git マージとは
Git リベースとは
別のブランチにリベースする方法
Git Rebase vs. Merge: どちらを使うべきか?
リベースするかリベースしないか?

Git 爆発

Linux カーネルで有名な Linus Torvalds は、他のバージョン管理システムとその遅い更新とコミットに不満を感じ、2005 年に 1 か月を費やして独自のバージョンを作成しました。 彼はそれを Git と名付けました。

GitHub、GitLab、BitBucket などのサイトは、共生的に Git を促進し、Git から恩恵を受けています。 今日、Git は世界中で使用されており、2022 年の調査では 71,000 人の回答者の 98% が Git をバージョン管理システムとして使用しています。

Git の主な設計上の決定事項の 1 つは速度でした。 特に、ブランチでの作業は可能な限り高速である必要がありました。 ブランチは、バージョン管理システムの基本的な部分です。 プロジェクト リポジトリには、メインまたはマスター ブランチがあります。 これは、プロジェクトのコード ベースが存在する場所です。 新機能などの開発は、分離されたサイド ブランチで行われます。 これにより、ブランチで行われた作業がマスター ブランチを台無しにするのを防ぎ、コード ベースのさまざまな部分で同時開発を行うことができます。

チームに適した Git ワークフローとブランチ モデルを選択する方法
関連チームに適した Git ワークフローと分岐モデルを選択する方法

サイド ブランチでの開発が完了すると、開発ブランチをマスター ブランチにマージすることにより、変更がマスター ブランチに転送されます。 他のバージョン管理システムでは、ブランチを操作するのは難しく、計算コストがかかりました。 Git でのブランチの操作は非常に高速で、非常に軽量です。 かつては面倒で、他のシステムでは避けることが多かった作業が、Git では些細なことになりました。

Git rebaseコマンドは、あるブランチから別のブランチに変更を転送する別の方法です。 mergeコマンドとrebaseコマンドの目的は似ていますが、異なる方法で目的を達成し、わずかに異なる結果が得られます。

Git マージとは

では、Git mergeコマンドは何のためにあるのでしょうか。 新しい機能に取り組むためにdev-branchというブランチを作成したとしましょう。

master ブランチとマージされていない dev-branch というブランチの図
Dave McKay/How-To Geek

いくつかのコミットを行い、新しい機能をテストします。 それはすべてうまくいきます。 ここで、新しい機能をmasterブランチに送信します。 別のブランチをマージするには、 masterブランチにいる必要があります。

マージする前に明示的にチェックアウトすることで、 masterブランチにいることを確認できます。

 git チェックアウト マスター

Git にdev-branchmasterブランチである current ブランチにマージするように指示できるようになりました。

 gitマージ開発ブランチ

dev-branch ブランチを master ブランチにマージする

mergeが完了しました。 masterブランチをチェックアウトしてコンパイルすると、新しく開発された機能が含まれます。 Git が実際に実行したのは、3 者間マージです。 masterブランチとdev-branchブランチの最新のコミットと、 dev-branchが作成される直前のmasterブランチのコミットを比較します。 次に、 masterブランチでコミットを実行します。

マージは、何も削除せず、Git 履歴を変更しないため、非破壊的であると見なされます。 dev-branchはまだ存在しており、以前のコミットは変更されていません。 3 方向マージの結果をキャプチャする新しいコミットが作成されます。

マージ後、Git リポジトリはタイムラインのように見え、別のラインが分岐してからメイン タイムラインに戻ります。

master ブランチにマージされた dev-branch ブランチ
デイブ・マッケイ/ハウツーオタク

dev-branchブランチがmasterブランチに組み込まれました。

1 つのプロジェクトに多数のブランチがある場合、プロジェクトの履歴が混乱する可能性があります。 これは、プロジェクトに多くの貢献者がいる場合によくあります。 開発作業はさまざまな経路に分かれるため、開発の歴史は直線的ではありません。 ブランチに独自のブランチがある場合、コミット履歴のもつれを解くことはさらに困難になります。

Git ブランチはどのように機能しますか?
関連Git ブランチはどのように機能しますか?

masterブランチにコミットされていない変更がある場合は、何かをマージする前に、これらの変更を処理する必要があることに注意してください。 新しいブランチを作成し、そこに変更をコミットしてから、マージを行うことができます。 次に、一時ブランチをマスター ブランチにマージする必要があります。

それは機能しますが、Git には、新しいブランチを作成せずに同じことを実現するコマンドがあります。 stashコマンドは、コミットされていない変更を保存し、 stash popでそれらを呼び出すことができます。

次のように使用します。

 隠し場所

gitマージ開発ブランチ

スタッシュ ポップ

最終結果はマージされたブランチであり、保存されていない変更が復元されます。

Git リベースとは

Git rebaseコマンドは、まったく異なる方法でその目的を達成します。 リベースしようとしているブランチからすべてのコミットを取得し、リベース先のブランチの最後にそれらをリプレイします。

前の例では、アクションを実行する前の Git リポジトリは次のようになっています。 dev-branchというブランチがあり、それらの変更をmasterブランチに移動したいと考えています。

master ブランチとマージされていない dev-branch というブランチの図
Dave McKay/How-To Geek

rebaseの後は、単一の完全に直線的な変更のタイムラインのように見えます。

dev-branch がリベースされた master ブランチ
デイブ・マッケイ/ハウツーオタク

dev-branchが削除され、 dev-branchのコミットが master ブランチに追加されました。 最終結果は、 dev-branchのコミットが最初にmasterブランチに実際に直接コミットされた場合と同じです。 コミットはmasterブランチに追加されるだけでなく、「再生」されて新たに追加されます。

これが、 rebaseコマンドが破壊的であると見なされる理由です。 リベースされたブランチは別のブランチとして存在しなくなり、プロジェクトの Git 履歴が書き直されました。 後の時点で、どのコミットが最初にdev-branchに対して行われたかを判断することはできません。

ただし、単純化された線形の履歴が残ります。 数十または数百ものブランチとマージがあるリポジトリと比較して、Git ログを読んだり、グラフィカルな git GUI を使用してリポジトリのグラフを表示したりすると、リベースされたリポジトリは簡単に理解できます。

別のブランチにリベースする方法

git rebaseの例を試してみましょう。 new-featureというブランチを持つプロジェクトがあります。 このブランチをmasterブランチにrebaseします。

まず、 masterブランチに未解決の変更がないことを確認します。

 git ステータス

new-featureブランチをチェックアウトします。

 git チェックアウトの新機能

現在のブランチを master ブランチにrebaseするように Git に指示します。

 git リベース マスター

まだ 2 つのブランチがあることがわかります。

 gitブランチ

masterブランチに戻します

git チェックアウト マスター

new-feature ブランチを current ブランチ (この場合はmasterブランチ) にマージします。

 git マージの新機能
新機能がリベースされたマスター ブランチ
デイブ・マッケイ/ハウツーオタク

興味深いことに、最終的なマージ後も 2 つのブランチが残っています。

Git branch コマンドを使用して、git リポジトリ内のブランチを一覧表示する
デイブ・マッケイ/ハウツーオタク

違いは、 new-featureブランチのヘッドとmasterブランチのヘッドが同じコミットを指すように設定されていることnew-feature 。支店のラベル。

dev-branch がリベースされた master ブランチ
デイブ・マッケイ/ハウツーオタク

Git Rebase vs. Merge: どちらを使うべきか?

rebasemergeの場合ではありません。 どちらも強力なコマンドであり、おそらく両方を使用するでしょう。 とはいえ、 rebaseがうまく機能しないユースケースもあります。 mergeを使用したミスによる unpick ミスは不快ですが、 rebaseによる unpick エラーは地獄です。

あなたがリポジトリを使用している唯一の開発者である場合、悲惨なrebaseを行う可能性は低くなります。 たとえば、間違った方向にrebaseし、マスター ブランチをnew-featureブランチにrebaseする可能性があります。 masterブランチを元に戻すには、今度はnew-featureブランチからmasterブランチに再度rebaseする必要があります。 奇妙に見える履歴ではありますが、それはあなたのmasterブランチを復元します.

他の人が作業する可能性が高い共有ブランチでは、 rebaseを使用しないでください。 リベースされたコードをリモート リポジトリにプッシュすると、リポジトリへの変更によって多くの人に問題が発生します。

プロジェクトに複数の貢献者がいる場合、安全なのはローカルリポジトリでのみrebaseを使用し、パブリック ブランチでは使用しないことです。 同様に、プル リクエストがコード レビューの一部である場合は、 rebaseを使用しないでください。 または、少なくとも、プル リクエストの作成後にrebaseを使用しないでください。 他の開発者があなたのコミットを見ている可能性があります。つまり、それらの変更はmasterブランチになくても、パブリック ブランチにあるということです。

危険なのは、既にリモート リポジトリにプッシュされているコミットをrebaseしようとしている場合であり、他の開発者が既にそれらのコミットに基づいて作業している可能性があります。 ローカルのrebaseにより、これらの既存のコミットが消滅します。 これらの変更をリポジトリにプッシュすると、人気がなくなります。

Git コミットを修正、編集、または元に戻す方法 (Git 履歴の変更)
関連Git コミットを修正、編集、または元に戻す方法 (Git 履歴の変更)

他の貢献者は、自分の作業をリポジトリに戻すために、面倒なmergeを行う必要があります。 その後、変更をローカル リポジトリに戻すと、重複した変更の混乱を解消することに直面します。

リベースするかリベースしないか?

プロジェクトでRebaseが禁止されている可能性があります。 地域的、文化的な異論があるかもしれません。 一部のプロジェクトや組織は、 rebaseを一種の異端であり、冒涜行為と見なしています。 Git の履歴は、何が起こったかの不可侵の永続的な記録であるべきだと考える人もいます。 したがって、 rebaseは検討の対象外になる可能性があります。

ただし、プライベート ブランチでローカルに使用する場合、 rebaseは便利なツールです。

リベースにプッシュし、開発者が自分だけのブランチに制限します。 または、少なくとも、すべての開発が停止し、他の誰もあなたのブランチのコミットに基づいて他の作業を行っていない場所。

そうすることで、問題を回避できます。

関連: Git のバージョンを確認して更新する方法