Git で再帰的ストラテジでマージする時のストラテジオプション ours と theirs の違い
2 つのブランチをマージする時にデフォルトで実行されるストラテジ, recursive (再帰的). その recursive で指定できる少しややこしい次の 2 つのオプション ours と theirs の違いをできるだけわかりやすく解説します.
Git のバージョンは 2.18.0
を前提にしております.
ours
と theirs
というオプションは, Git の再帰的マージストラテジで指定できるオプションです.
なので git merge -s recursive -X <option> <branch>
という構文の <option>
にあたります.
また -s recursive
の部分は, git merge <branch>
と 1 つの <branch>
をマージする場合はデフォルトで再帰的マージになりますので省略可能です.
つまりは ours
もしくは theirs
オプションを指定する場合, git merge -X <option> <branch>
という構文が普段使いに最適です.
でお次は本題の ours
もしくは theirs
オプションを使うとどのようになるのかということを説明します.
まず次のようなヒストリがあるとします:
A <- feature
/
/
B -- C --- D <- master <- HEAD
そして何もオプションを付けないで, feature
ブランチを master
ブランチにマージさせます:
git merge feature
すると次のようなメッセージが表示され:
Auto-merging example.txt
CONFLICT (content): Merge conflict in example.txt
Automatic merge failed; fix conflicts and then commit the result.
example.txt
に次のようなマージコンフリクトが発生したとします:
The first line by branch 'master'.
The second line by branch 'master'.
<<<<<<< HEAD
The third line by branch 'master'.
=======
The third line by branch 'feature'.
>>>>>>> feature
このマージコンフリクトの内容から HEAD
(master
ブランチ) の The third line by branch 'master'.
と feature
ブランチの The third line by branch 'feature'.
が競合しているというのか確認できます.
このようなマージコンフリクトが ours
もしくは theirs
オプションを使うとどのように解決されるのか見てみたいと思います.
ours
オプションを使った場合
まず ours
オプションを使った場合, マージする時に競合する部分はマージされるブランチのものを優遇します. つまりは git merge -X ours <branch>
で <branch>
をマージする時に, <branch>
の方ではなく, HEAD
の方を優遇します.
マージするブランチではなくマージされるブランチの方がが本流と捉えられるので, ours
(私たちのもの) となります.
なので先ほどのヒストリの場合, ours
オプションを使って feature
ブランチをマージすると:
git merge -X ours feature
次のようなメッセージが表示され:
Auto-merging example.txt
Merge made by the 'recursive' strategy.
マージコンフリクトは発生せず, example.txt
は次のようになります:
The first line by branch 'master'.
The second line by branch 'master'.
The third line by branch 'master'.
このように ours
オプションを使うと, 競合する部分はマージされるブランチ (master
) の方のバージョンを優遇します.
theirs
オプションを使った場合
一方の theirs
オプションを使うと, ours
オプションとは逆になり, マージする時に競合する部分はマージするブランチのものを優遇します. つまりは git merge -X theirs <branch>
で <branch>
をマージする時に, HEAD
ではなく <branch>
の方を優遇します.
マージされるブランチが本流と捉えられるのに対し, マージするブランチは支流と捉えられるので, theirs
(彼ら彼女らのもの) となります.
同じく先ほどのヒストリの場合, theirs
オプションを使って feature
ブランチをマージすると:
git merge -X theirs feature
次のようなメッセージが表示され:
Auto-merging example.txt
Merge made by the 'recursive' strategy.
example.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
マージコンフリクトは発生せず, example.txt
は次のようになります:
The first line by branch 'master'.
The second line by branch 'master'.
The third line by branch 'feature'.
このように theirs
オプションを使うと, 競合する部分はマージするブランチ (feature
) の方のバージョンを優遇します.
まとめ
再帰的マージでマージコンフリクトが発生した場合, マージされる方, する方どちらのブランチを優遇するかというのは次のようになります:
git merge -X ours <branch>
の場合,<branch>
をマージするHEAD
の方を優遇します.git merge -X theirs <branch>
の場合,HEAD
にマージする<branch>
の方を優遇します.
ところで競合が発生しないマージの場合, ours
もしくは theirs
オプションのどちらを使ってもマージ結果に違いが出ることはありません.
あくまで競合が発生した場合どちらの方のブランチを優遇させるかというオプションになりますので.
あと別のマージストラテジとして ours
というものがありますが, そちらはマージストラテジのオプションではなく, マージストラテジの一つなので, 再帰的マージストラテジの ours
オプションとの混同に注意していただければと思います.
例えば ours
マージストラテジで feature
ブランチを HEAD
にマージする場合:
git merge -s ours feature
git merge -X ours feature
の場合と異なり, feature
ブランチのバージョンのものが HEAD
のバージョンのものと競合していようがしていまいが, feature
ブランチの内容を HEAD
にマージさせるということは一切行いません.
feature
ブランチの内容のものは全て無視されマージされません.
じゃあその ours
マージストラテジでマージする意味ってなんなのということですが, この場合 feature
ブランチに HEAD
が取って代わりますよという時に使われます.
このようにマージストラテジの ours
は形だけのマージですので, 再帰的マージの ours
オプションとは全く異なるものです.
と少し今回の内容から逸れてしまいましたが, 今回の内容が再帰的マージストラテジの 2 つのオプション ours
と theirs
の違いを理解するお役に立つことができましたでしょうか.
参考資料
関連記事
Git の merge.conflictStyle を merge から diff3 に変更したら, マージコンフリクトがより解決しやすくなった2018.08.19
Git の mergetool で vimdiff を指定して Vim でマージコンフリクトを解決してみた2018.08.20
Git の 3-way マージで共通祖先が 2 つの場合, 共通祖先はどんな感じになるのか調べてみた2018.08.22
Git のファストフォワードマージとは2018.08.15
Git の 'detached HEAD' 状態とその注意点2018.05.31