これはなに

Gitで、新しいブランチを作成したあと、もとのブランチに更新が入ったときに、どうすればいいのかのメモ。
前提条件

- Gitの基本的な使い方を知っている
- コマンドラインでGitを操作できる
はじめに

Gitを利用する際、たとえばmainブランチから新しいブランチを作成したあと、mainブランチに更新が入ることはよくある。そのときに、mainブランチの最新の変更を新しいブランチに取り込みたいことがある。
以下では、もとのブランチがmainブランチで、新しいブランチがnew-branchであると仮定して説明する。ただし、この方法は特段mainブランチに限らず、どのブランチに対しても適用できる。
対応方法の種類

最新の変更を取り込む方法は大別して2つある。
- 新しいブランチの開始点を、
mainブランチの最新のコミットへ移動する mainブランチの最新のコミットを、新しいブランチへ取り込む
基本的に、新しいブランチにまだコミットがない場合は1、すでにコミットがある場合は2の方法を取る。 ただし、新しいブランチにコミットがあっても、まだリモートリポジトリにプッシュしていない場合は、1の方法でも問題ない。
事前の準備:作業状態の保存

変更を取り込む前に、git stashコマンドで現在の作業状態を保存しておくことをオススメする。これにより、操作中に問題が発生した場合でも、簡単に元の状態に戻せる。
git stash save "作業中の変更を一時保存"この操作により、現在の変更が一時的に保存され、作業ディレクトリがクリーンな状態になる。 後述する操作で変更の取り込みが完了した後、保存した変更は次の操作で復元できる。
git stash poppopオプションを指定することで、最後に保存した変更を復元できる。
手順

新しいブランチの開始点を移動する

この方法は、以下の場合に使える。この方法はコミット履歴を変更してしまうため、リモートリポジトリへプッシュした後は使えない。
- 新しいブランチを作成しただけで、まだ何もコミットしていない場合
- 新しいブランチを作成し、すぐにコミットしているが、まだリモートリポジトリへプッシュしていない場合
まず、新しいブランチに切り替える1。
git switch new-branchその後、mainブランチの最新の状態へリベースする。
git rebase mainこれにより、新しいブランチの開始点を、mainブランチの最新のコミットへ移動できる。
コンフリクトが発生した場合は、コンフリクトを解消してからgit rebase --continueを実行する。
くれぐれも、すでにリモートリポジトリへプッシュしている場合は、rebaseを使ってはならない。なぜなら、rebaseは履歴を書き換える操作だからである。
リモートリポジトリへプッシュした後にrebaseでローカルリポジトリの履歴を書き換えてしまうと、リモートリポジトリとローカルリポジトリとで、コミット履歴の整合性が取れなくなってしまう。
もし、すでに新しいブランチでコミットしていて、リモートリポジトリにプッシュしている場合は、次に述べるmergeを使う。
新しいブランチに最新のコミットを取り込む

この方法は、以下の場合に使える。この方法はコミット履歴を書き換えないため、リモートリポジトリへプッシュした後でも使える。
- 新しく作成したブランチにすでにコミットがあり、かつ、すでにリモートリポジトリへプッシュしている場合
まず、新しいブランチに切り替える。
git switch new-branchその後、mainブランチの最新の状態をマージする。
git merge mainこれにより、新しいブランチに、mainブランチの最新の状態を取り込める。ブランチの開始点は変わらないが、履歴を書き換えずに、新しいブランチの状態をmainブランチの最新のコミットへ合わせられる。
マージの際にコミットが作成される点には注意すること。
コンフリクトが発生した場合は、コンフリクトを解消してから通常のコミットを行う。
Appendix | コンフリクトの対処

rebaseやmergeの際に、同じファイルの同じ部分が両方のブランチで変更されていると、コンフリクトが発生しうる。コンフリクトが発生した場合は、Gitは自動的にマージを停止し、手動での解決を求める。
コンフリクトが発生した場合の一般的な手順は以下のとおりである。本稿では詳細な説明は省略する。
- コンフリクトしたファイルを開く
- コンフリクトのある部分を探す
- 望ましい最終的な内容に編集し、コンフリクトを解決する
- 変更をステージングエリアに追加する
- コンフリクト解決後、
rebaseの場合はgit rebase --continueを、mergeの場合は通常のコミットを行う
まとめ

新しいブランチを作成した後、もとのブランチに更新が入ったときは、以下の方法で対応できる。
- 新しいブランチにまだコミットがない場合は、
rebaseを利用して、新しいブランチの開始点をmainブランチの最新のコミットへ移動する - 新しいブランチにすでにコミットがある場合、とくにリモートリポジトリへプッシュした後の場合は、
mergeを利用して、mainブランチの最新のコミットを新しいブランチへ取り込む
git switchはGit 2.23以降で利用可能。それ以前のバージョンではgit checkoutを使う。 ↩︎