今回は、Gitにおけるmergeの基本について書きたいと思います。
本当はrebaseとかを書くつもりで調べ始めたのですが、
そもそもmergeの知識もふわっとしてるな…と思い書くことにしました。
mergeとは
git-merge - Join two or more development histories together
直訳すると「2つ以上の開発履歴を結合する」とのことです。
以下を実行すると、今いるブランチに結合したいブランチをマージできます。
$ git merge 結合したいブランチ名
いつmergeするのか
マージするタイミングは大きく分けて2つ考えられます。
- 目的としていた作業が終わり、mainブランチに変更を反映したいとき
$ git merge 作業用ブランチ名
- 作業用ブランチにmainブランチ上の新しいコミットを反映させたいとき
$ git merge mainブランチ
merge前の注意点
インデックスや作業用ディレクトリを空にしておくこと!
$ git status
でファイルが表示されなければOKです。
mergeの分類
Fast forward merge
コミットを作らないマージ。
あるコミットに対してコミット履歴上で直接到達できる別のコミットをマージしようとした場合にFast-forward mergeが実行されます。
つまり、マージ対象が分岐していなくて同一直線上にあるときに起こります。
Gitは単にポインタを前に進めるだけです。
実行例
$ git merge test1 Updating 8ecdf8d..935a8d0 Fast-forward rebase-test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Fast-forward
と表示されます。
True merge
コミットをつくるマージ。non-fast-forward mergeとも言われます。
「両方のブランチを親とするマージコミットによって結合される必要がある」と書いてありました。
先述と同じように書くなら、マージ対象が分岐していて同一直線上にいないときに起こります。
作成されたマージコミットには親が2つあります。(通常のコミットは親は1つ)
実行例
$ git merge test2 Merge made by the 'ort' strategy. irb.rb | 2 +- revert-test.rb | 1 - sort.js | 18 ------------------ sub.rb | 1 - 4 files changed, 1 insertion(+), 21 deletions(-) 以下略
Merge made by the '~' strategy.
という文が表示されます。
'~'
にはマージストラテジーの種類が入ります。
Merge Strategyとは
マージする戦略(基準みたいなもの)。デフォルトはort
。
オプションでマージストラテジーを指定することができます。
マージストラテジーの種類↓
・ort
・recursive
・resolve
・octopus
・ours
・subtree
詳しくはこちらを参考↓
Git - git-merge Documentation
mergeの例
なんとなくのイメージをつかむために例を書いていきます!
- プロジェクトのissueに対応するために、mainブランチから作業用ブランチ(issueブランチとする)に切り替えて作業をしていた。(コミット2)
急ぎで対応しないといけない問題が発生!
一旦mainブランチへ戻り、別の急ぎ修正用ブランチ(hotfixブランチとする)を作成し、hotfixブランチで修正を行なった。(コミット3)
- mainブランチに戻り、hotfixブランチをmergeした。
★ここは一直線上なのでfast-forward merge!
- hotfixブランチを削除後、mainブランチからissueブランチへ移動して、再度作業した。(コミット4)
★この時点でhotfixブランチで行った作業はissueブランチには含まれていない!
- issueの対応が終わったので、mainブランチに移動しissueブランチをmergeした。
★ここはtrue merge!マージコミット(コミット5)ができています。
親はコミット3とコミット4です。
参考リンク↓
Git - ブランチとマージの基本
コンフリクト発生
true mergeではコンフリクト(競合)が起こることがあります。
同じファイルの重複部分が変更されていると変更同士が衝突してコンフリクトが起こります。
コンフリクトが起きると、マージは一旦中断されます。
その後の対応は2種類あります。
mergeをやめる
$ git merge --abort
これでマージしようとしたことをなしにできます。
コンフリクトを解消してmergeする
詳しい手順は以下の通りです。
- コンフリクトしているファイルを確認する
$ git status
実行して表示されるUnmerged paths:
と書かれた後に、コンフリクトしているファイルが表示されます。
それらのファイルをコンフリクトがない状態に修正し保存
2つのコミットの差分が表示されるのでそれらを修正します。競合していたファイルをステージングしコミット
$ git add ファイル名 $ git commit
- マージ完了!
マージが完了した時点でマージコミットが作られます。
おわりに
今回はmergeの基本について書いていきました。
長かったですね。笑
mergeのことをこんなに考えたのは初めてだったので勉強になりました。
参考になれば幸いです。
間違い等あればご指導いただければと思います。
参考リンク
おわります👋