rebase を使用して変更を適用する
[アーティクル] 03/25/2024
9 人の共同作成者
フィードバック
この記事の内容
Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019
Visual Studio 2019 | Visual Studio 2022
Git では、新しいコミット のたびにその前任者にリンクすることで、ブランチ での開発履歴 が自動的に保持されます。 あるブランチを別のブランチにマージ すると、履歴の単純さが低下する可能性があります。 たとえば、早送りなしのマージ では、複数の先行処理を含むマージ コミットを作成することで、多様な開発行が結合されます。 逆に、Git リベース では、マージ コミットを作成せずに多様な開発行を結合することにより、コミット履歴が単純になりますが、マージに関する情報は失われます。 マージの種類 の選択は、マージの記録を保持するか、コミット履歴を簡略化するかによって影響を受ける可能性があります。
この記事では、早送りなしのマージではなくリベースを使用すべき状況について説明し、次のタスクの手順を示します。
ローカル ブランチのリベース
リベース後にローカル ブランチを強制的にプッシュする
ローカル コミットをスカッシュするための対話型リベース
Git ワークフローの概要については、Azure Repos Git チュートリアル 参照してください。
ローカル ブランチのリベース
Git リベース では、ソース ブランチからのコミットを現在のローカル ブランチ (ターゲット ブランチ) に統合します。 ソース ブランチは変更されません。 比較のために、Git リベースとその他のマージの種類を次の図に示します。
Git リベースでは、ターゲット ブランチのコミット履歴を並べ替え、すべてのソース ブランチ コミットに続き、最後の共通コミット以降のすべてのターゲット ブランチ コミットが格納されます。 これについて別の見方をすると、リベースでは、ソース ブランチの履歴上でターゲット ブランチの変更が再現されます。 注目点として、Git リベースでは、既存のターゲット ブランチ コミットのシーケンスが変更されます。これは、他のマージ方法では起こりません。 前の図では、コミット K' には K と同じ変更が含まれていますが、C ではなくコミット E がリンク元であるため、新しいコミット ID が付けられます。
リベース中に、ソース ブランチの変更がいずれかのターゲット ブランチの変更と競合する場合、Git ではマージの競合を解決する ことを求めるメッセージが表示されます。 マージ中にマージ競合を解決するのと同じ方法で、リベース中にマージ競合を解決できます。
リベースと早送りなしのマージ
Git リベースは、早送りなしの マージ ("3 方向" または "真の" マージとも呼ばれる) に比べて結果は単純になりますが、コミット履歴の正確さは低下します。 コミット履歴にマージの記録が必要な場合は、早送りなしのマージを使用します。
機能ブランチまたはバグ修正ブランチで作業しているユーザーが自分だけの場合は、リベースを使用して、最近の main
ブランチの作業をそれに定期的に統合することを検討してください。 この戦略は、他のユーザーによる最近の作業を把握し、発生したマージ競合を迅速に解決するのに役立ちます。 リベースすることで、自分の新しい機能を最新の main
ブランチ作業の上に実装し、直線的なコミット履歴を維持するのに役立ちます。
Git リベースの詳細と、それを使用する状況については、「リベースとマージ 」を参照してください。
リベースと強制プッシュのガイドライン
以前プッシュ したローカル ブランチをリベースし、既定の Git プッシュ コマンドをもう一度実行すると、プッシュは失敗します。 既定の Git プッシュ コマンドでは、早送りマージを適用して、ローカル ブランチをリモート ブランチに統合します。 このコマンドはリベース後に失敗します。これは、リベースによってローカル ターゲット ブランチ内の既存のコミットのシーケンスが変更されるため、リモート ターゲット ブランチの履歴と一致しなくなるためです。 このシナリオでは、リモート ブランチを上書きすることで、強制プッシュ が成功します。
Git リベースと強制プッシュは強力なツールですが、使用するかどうかを決定するときは、次のガイドラインに留意してください。
共有ブランチを誰も使用していないことが確かな場合を除き、プッシュされて他のユーザーと共有されているローカル ブランチをリベースしないでください。 リベースした後、ローカル ブランチはリモートブランチの履歴と一致しなくなります。
他のユーザーが使用しているリモート ブランチに強制プッシュしないでください。そのリモート ブランチのローカル バージョンが、更新されたリモート ブランチ履歴と一致しなくなるためです。
リベースと強制プッシュの使用シナリオにチームが同意する必要があります。
ヒント
協調的レビュー プロセスの場合は、pull request を使用して、リモート リポジトリの既定のブランチに新しい作業をマージします。
リベースする方法
Visual Studio 2022 は、[Git] メニュー、[Git 変更] 、および [ソリューション エクスプローラー] のコンテキスト メニューを使用して、Git バージョン管理エクスペリエンスを提供します。 Visual Studio 2019 バージョン 16.8 には、チーム エクスプローラー の Git ユーザー インターフェイスも用意されています。 詳細については、「Visual Studio 2019 - チーム エクスプローラー 」タブを参照してください。
[Git]>[ブランチの管理] を選択して、[Git リポジトリ] ウィンドウを開きます。
[Git リポジトリ] ウィンドウで、ターゲット ブランチを右クリックし、[チェックアウト] を選択します。
ソース ブランチを右クリックし、[<target-branch> を <source-branch> にリベースする] を選択します。
リベースが成功すると、Visual Studio が確認メッセージを表示します。
マージの競合が原因でリベースが停止した場合、Visual Studio から通知されます。 競合を解決 するか、リベースを取り消してリベース前の状態に戻すことができます。
Visual Studio 2019 バージョン 16.8 以降のバージョンでは、チーム エクスプローラー の Git ユーザー インターフェイスが維持される一方、Git バージョン コントロール エクスペリエンスが提供されます。 チーム エクスプローラー を使用するには、メニュー バーで [ツール] >[オプション] >[プレビュー機能] >[New Git User Experience] (新しい Git ユーザー エクスペリエンス) のチェック ボックスをオフにします。 どちらのインターフェイスからも Git 機能を同じように使用できます。
チーム エクスプローラー で、[ホーム] を選択し、[ブランチ] を選択します。
[ブランチ] ビューで、ターゲット ブランチを右クリックし、[チェックアウト] を選択します。
ソース ブランチを右クリックし、[リベース対象] を選択します。
リベース オプションを確認し、[リベース] をクリックします。
リベースが成功すると、Visual Studio が確認メッセージを表示します。
リベース中に競合が発生した場合、Visual Studio から通知されます。 競合を解決 するか、リベースを取り消してリベース前の状態に戻すことができます。
ソース ブランチのコミットをターゲット ブランチに統合するには、git rebase
コマンドを実行します。
git rebase <source branch name> <target branch name>
現在のローカル ブランチがターゲット ブランチの場合は、次のようにリベース コマンドを簡略化できます。
git rebase <source branch name>
リベース中に競合が発生した場合、Git から通知されます。 競合を解決 してから git rebase --continue
を実行するか、git rebase --abort
を実行してリベースを取り消してリベース前の状態に戻すことができます。
リベース後にローカル ブランチを強制的にプッシュする
以前プッシュしたローカル ブランチをリベースすると、後続の既定の Git プッシュは失敗します 。 代わりに、ローカル ブランチを強制プッシュして、対応するリモート ブランチを上書きし、コミット履歴が一致するようにすることができます。
Visual Studio で強制プッシュを実行するには、最初に強制プッシュ オプションを有効にする必要があります。
[ツール] >[オプション] >[ソース管理] >[Git グローバル設定] の順に移動します。
[push --force-with-lease を有効にする] オプションを選択します。
Git push --force-with-lease
フラグは --force
フラグよりも安全です。これは、強制プッシュするローカル ブランチ内で統合されないコミットを持つリモート ブランチを上書きしないためです。
[Git 変更] ウィンドウで、プッシュ ボタンを選択してコミットをプッシュします。
または、[Git] メニューから [プッシュ] を選択することもできます。
既定の Git プッシュ操作が失敗した場合、Visual Studio では [Git - プッシュに失敗しました] ダイアログが起動します。 [強制プッシュ] を選択します。
プッシュが成功すると、Visual Studio が確認メッセージを表示します。
Visual Studio 2019 バージョン 16.8 以降のバージョンでは、チーム エクスプローラー の Git ユーザー インターフェイスが維持される一方、Git バージョン コントロール エクスペリエンスが提供されます。 チーム エクスプローラー を使用するには、メニュー バーで [ツール] >[オプション] >[プレビュー機能] >[New Git User Experience] (新しい Git ユーザー エクスペリエンス) のチェック ボックスをオフにします。 どちらのインターフェイスからも Git 機能を同じように使用できます。
チーム エクスプローラー で、[ホーム] を選択し、次に [同期] を選択して [同期] ビューを開きます。
[同期] ビューで [プッシュ] を選択して、変更をリモート リポジトリにアップロードします。
既定の Git プッシュ操作が失敗した場合、Visual Studio では [Git - プッシュに失敗しました] ダイアログが起動します。 [強制プッシュ] を選択します。
プッシュが成功すると、Visual Studio が確認メッセージを表示します。
ヒント
Git push --force-with-lease
フラグは --force
フラグよりも安全です。これは、強制プッシュするローカル ブランチ内で統合されないコミットを持つリモート ブランチを上書きしないためです。
ローカル ブランチから同じ名前のリモート ブランチに新しいコミットを強制プッシュするには:
git push --force-with-lease <remote> <local branch name>
プッシュするブランチがチェックアウトされたブランチである場合は、強制プッシュ コマンドを次のように簡略化できます。
git push --force-with-lease <remote>
リモート リポジトリをクローンすると、Git では、クローンしたリモート リポジトリの URL の短縮形としてエイリアス origin
が割り当てられます。 git remote -v
を実行して origin
エイリアス値を確認します。 origin
エイリアスを手動で追加するには、git remote add origin <remote repo url>
を実行します。 origin
エイリアスを使用すると、強制プッシュ コマンドをさらに簡略化できます。
git push --force-with-lease origin
現在のローカル ブランチが origin
のリモート ブランチを追跡している場合は、強制プッシュ コマンドを完全に省略できます。
git push --force-with-lease
ただし、ローカル ブランチがリモート ブランチを追跡していない場合、プッシュ コマンドを完全に省略すると失敗します。 git remote show origin
を実行して、ブランチの追跡状態をチェックします。
ローカル コミットをスカッシュするための対話型リベース
通常、ローカル機能ブランチで新しい機能について作業する場合は、複数のコミットを作成します。 新しい機能を発行する準備ができたら、それらのコミットを 1 つのコミットに統合してコミット履歴を簡略化することができます。 対話型リベースを使用して、複数のコミットを 1 つのコミットに "スカッシュ" できます。
Visual Studio 2022 では、対話型リベースはサポートされていません。 代わりに Git コマンド ラインを使用してください。
Visual Studio 2019 では、対話型リベースはサポートされていません。 代わりに Git コマンド ラインを使用してください。
対話型リベースを実行するローカル ブランチをチェックアウトします。
コミットされていない変更をコミット 、スタッシュ、または破棄します。
コミット履歴をどれだけ遡るか見積もります。 対話型リベース コマンドを実行するときは、スカッシュする特定のコミットを選択することになるため、正確でなくてもかまいません。 たとえば、最後の 5 つのコミット内でコミットをスカッシュする場合は、次を実行します。
git rebase -i HEAD~5
Git でエディターが開き、最後の 5 つのコミットが、最新のものから一覧表示されます。 例:
pick 7068b09 Update README network switch section
pick 9d247f7 Update README network controller section
pick 5d7ab9f Fix fiber optic transmitter test
pick 7b43f3f Add network switch test
pick 00859d9 Add network controller test
最初の行はそのままにしておきます。 後続の行で、コミットをその上のコミットとマージするには、pick
を squash
に変更します。 たとえば、先頭の 2 つのコミットと末尾の 2 つのコミットを組み合わせるには、コミット リストを次のように変更します。
pick 7068b09 Update README network switch section
squash 9d247f7 Update README network controller section
pick 5d7ab9f Fix fiber optic transmitter test
pick 7b43f3f Add network switch test
squash 00859d9 Add network controller test
保存してエディターを閉じます。 Git ではその後、マージされたコミットのセットごとに新しいエディターが開き、コミット メッセージを入力するように求められます。 コミット セットごとに、コミット メッセージを 1 つのメッセージに圧縮してから、保存してエディターを閉じます。 前の例では、スカッシュされたコミットは新しいコミット メッセージと一緒に圧縮されています。
8fcb88f Update README network sections
ac6d3c0 Fix fiber optic transmitter test
f0aadc3 Add two network tests
コミット Fix fiber optic transmitter test
はスカッシュされませんでしたが、別の専攻処理コミットにリンクされるようになったため、新しいコミット IDが追加されました。
対話型リベースの詳細については、Git リベース対話型モード に関する記事を参照してください。
Note
Azure DevOps ユーザーはマージをスカッシュ して、pull request 中にトピック ブランチのコミット履歴を要約できます。
次のステップ
関連記事