ブランチの差分を別のブランチに適用する - Git による版管理環境を構築する

SPECIAL


ブランチの差分を別のブランチに適用する

Git では、マージやリベースという機能を使って、別々のブランチを 1 つに結合することができます。

たとえば、次のようなブランチがあったとして、リベース機能で結合する方法について見てみます。

まず、"master" ブランチが主流となるブランチです。

コミット "COMMIT B" の段階で "fix1" ブランチでの制作を始めた後、"master" での作業も並行して進めています。

途中 "COMMIT C" の段階で "improve1" ブランチでの制作を始め、さらにその "improve1" ブランチの制作途中で、そこから "improve2" ブランチでの制作を始め、それぞれのブランチで並行して制作作業を進めています。

 

もし、リベースの最中にコンフリクト(衝突)が発生した場合には、まずは マージ と同じようにコンフリクトを解消して、解消したファイルをステージングした後で、コミットではなく次のように、コンフリクトが解消したことを知らせます。

git rebase --continue

そうすることで、リベース処理が継続されて行き、全てのリベース処理が終われば結合完了です。

もしコンフリクト解消の途中で、リベース処理を中止して、リベース前の元の状態に戻したい場合には、次のようにします。

git rebase --abort

 

あるブランチを master ブランチにリベースする

ここで、"fix1" の修正が完了したとして、これを今回は "リベース" を使って "master" ブランチに結合してみます。

そのためには、今度はこれまでの "マージ" による方法とはちがって、まずは変更先のブランチである "fix1" に切り替えます。その上で、"git rebase master" を実行して、"fix1" を "COMMIT B" ではなく "master" ブランチからの修正だったものとすることができます。

git checkout fix1

git rebase master

このようにすることで、これまで "COMMIT B" から派生して "fix1" で行っていた修正を、あたかも現時点での "master" から始めていたかのようにすることができます。

同じことを、次の 1 つのコマンドでも実現することができるようでした。

git rebase master fix1

こうすることで、"fix1" ブランチが、当初 "master" ブランチから分岐した変更としてではなく、現時点の "master" ブランチからの修正かのように "fix1" ブランチの内容が置き変わりました。

 

このときのブランチの構成図としては、次のような感じになります。

ブランチを マージ した時とは雰囲気が随分変わって、"master" ブランチの先に "fix1" ブランチが移動したような感じです。つまり、"fix1" で行った変更が、パッチとして "master" ブランチに適用された感じになります。

後は "master" ブランチに戻って、"fix1" をマージしてあげれば、"master" ブランチを最新のコミット位置へ移動することができます。

操作としては、次のような流れになります。

git checkout master

git merge fix1

修正作業が完了したら "git branch -d fix1" として、不要になった "fix1" ブランチを削除してあげるとすっきりします。

 

二つのブランチ間の差分を master ブランチに適用する

リベースによる結合では、とある 2 つのブランチを使って差分を取って、それを別のブランチに適用することができます。

たとえば次の構成で、そのようなことを見て行きます。

たとえば "improve2" が、"improve1" から分岐した時点から現在までの更新内容を "master" ブランチに適用したい場合には、次のようにします。

git rebase --onto "master" "improve1" "improve2"

"--onto" で差分を適用したいブランチを指定して、その後の引数で、どのブランチから差分を作るかを指定しています。

差分は、最初に指定したブランチの系統からの分岐点(上記では "COMMIT C1-A")から、後で指定したブランチの場所(上記では "COMMIT C1-A2-B")までの変更内容となります。

 

上記のコマンドを実行することにより、まず "improve2" がチェックアウトされた後、"improve1" から分岐した時点からの更新内容が、"--onto" で指定したブランチに適用される感じになります。

つまり、"improve2" ブランチが、当初の分岐点である "COMMIT C1-A" からの更新ではなく、あたかも "master" ブランチが指している "COMMIT B'1-A" からの更新だったかのように、"improve2" ブランチが移動することになります。

後は "master" ブランチに戻って、"improve2" にマージしてあげれば、"master" ブランチを最新のコミット位置へ移動することができます。

git checkout master

git merge improve2

ここまでできたら、"git branch -d improve2" として、不要になった "improve2" ブランチを削除してあげるとすっきりします。

 

目次