ブランチの差分を別のブランチに適用する - 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" ブランチを削除してあげるとすっきりします。
【目次】