前回mergetoolの設定などを行ったので今回は実際にUnityで開発をしてコンフリクト発生させてみよう。
Masterブランチ
現在Masterブランチにいることを確認し、Unity上で以下の作業をする。
1.Createから新規Cubeを作成し、transformを以下のように設定する。
2.CreateからSphereを作成し、tansformを以下のように設定する。
3.この状態をMasterブランチの状態にしよう。CTR+Sでプロジェクトを保存する。
4.ターミナルに戻ってこの状態をAdd&Commitする。コマンドは以下
$ git add .
$ git commit -m"first-commit"
featAブランチの作成
それではブランチを切っていこう。ここではfeatAというブランチを作成し、checkoutする。コマンドは以下
$ git checkout -b featA
Unityに戻って、ボールのtransformを以下のように変更する。
保存して(ctr+s)から、ターミナルに戻って以下のコマンド打つ
$ git add .
$ git commit -m"ボールのx座標を10に設定"
Masterに戻る
再びmasterブランチに戻り。今度はfeatBブランチを作成する。コマンドは以下
(checkout -で1回前のブランチに移動する)
$ git checkout -
$ git checkout -b featB
Unityに戻って(ボールが初期位置に来ている)。今度はボールのx座標を-5に設定する。
保存して(ctr+s)ターミナルに戻ってadd & commit するコマンドは以下
$ git add .
$ git commit -m"ボールの位置を-5に設定"
merge
これでMasterブランチから、ボールの位置が異なっているブランチが2つあることになった。では実際にmergeしていこう。masterブランチに移動し、まずはfeatAをmergeする。コマンドは以下
$ git checkout -
$ git merge featA
このmergeは全く問題ない。masterからの差分はボールの位置を10に変更しただけなのでfast-forwardでmergeされる。
恐怖のCONFLICT発生!
それでは引き続きmasterブランチにfeatBブランチをmergeしてみよう。
コマンドは以下
$ git merge featB
ここで恐怖のCONFLICTが発生した。
Assets/Scenes/SampleScene.unity
というファイルでCONFLICTが発生したとメッセージが表示されている。
まず、CONFLICTが発生した原因だが、featAが保持していた、masterブランチからの差分ボールの位置を10にするという変更と、featBが保持していたmasterブランチからの差分ボールの位置を-5にするという情報が矛盾していていてGitはどちらを採用してよいかわからないからだ。
コンフリクト解消方法
コンフリクト解消方法はいくつかあるがまずは一番消極的(簡単)な方法から実践していこう。
git merge –abort
まずはこのコマンドを知っておこう。abortとは中止、中断するという意味の英単語でこの場合はmergeするという行為自体をやめたいときに行う。CONFLICTが発生してしまった場合で対処が難しそうな場合に利用する。実はこのコマンドの使用頻度は割と高い。さっそく使ってみようコマンドは以下
$ git merge --abort
master|MERGINGの表記が消え、mergeが中止されたことがわかる
–ours
$ git checkout --ours ファイル名
git checkout に–oursオプションをつけてファイルを指定すると矛盾している部分に現在のブランチの内容を採用する。現在masterブランチはfeatAブランチをmergeしてあるのでボール位置は10だ。そこにボールの位置を-5にするというブランチをmergeしようとした場合。–oursオプションをつけると現在のブランチの状況つまりx座標が10の状態を採用する。実際のコマンドは以下
$ git checkout --ours Assets/Scenes/SampleScene.unity
まだ、mergeは終わっていない。この後、add & commitしてmerge作業は終了となる。実際のコマンドは以下
$ git add .
$ git commit -m"コンフリクトが発生さたのでmasterを採用"
こうすることによって無事にMERGINGが終了する。
巻き戻し
mergeが完了してしまったので、一旦masterブランチをmergeする前(first_commit)の状態まで戻そう。コマンドは以下
$ git reset --hard HEAD~~
これでmasterブランチを最初の状態に戻すことができる。
HEAD~で一つ前の状態
HEAD~~で2つ前の状態
HEADの後ろの~の数で遡るcommit数を決める。
–theirs
再び2つのブランチをmergeしてCONFLICTを発生させよう。今度は先程とは逆の–theiersを使う。
これは取り込みたいブランチを優先して採用する。コマンドは以下
$ git checkout --theirs Assets/Scenes/SampleScene.unity
$ git add .
$ git commit -m"コンフリクトが発生したのでfeatBブランチを優先して取り込み"
エディターで確認しながら修正
ここでまた以下のコマンドでCONFLICTを発生させる
$ git reset --hard HEAD~~
$ git merge featA
$ git merge featB
–oursや–theirsではなく、実際にどちらの変更を取り込むのか目視で確認しながら行いた場合はそのファイルを目指しながら直す方法がある。ここではvimでそのファイルを開いてみよう。コマンドは以下
$ vi Assets/Scenes/SampleScene.unity
ぐぇ〜。そうUnityでのバージョン管理を難しくしている要因の一つにデータがYAML形式で扱われている点がある。しかも管理している項目が多いので行数も多い。(今回は約500行あった)
コンフリクトしている部分には
=======
という表記があるのでvimでこれを検索してみよう。コマンドは以下(vim操作)
/=
コンフリクトしている部分に飛んでいけるのでここを修正する。今回はxが10となるようにファイルを編集する。
編集が終わったら:wqしてvimを抜ける。その後は先程と同じようにファイルをadd & commit してmerge終了となる。実際のコマンドは以下
$ git add .
$ git commit -m"コンフリクトが発生。今回はxは10を採用"
これで無事コンフリクトを解消することができた。
P4merge
ファイルの行数は多いし、YAMLは見ずら・・・
そんな状態の手助けそしてくれるのが、前回設定したP4mergeだ。
再びコンフリクトを発生させよう。こんどはこの状態で以下のコマンドを打つ
$ git mergetool
うぉぉ!ちゃんと前回の設定が完了していると、P4mergeツールが起動する。
これは先程エディタでやった作業をグラフィカルに表示し、状態を選択できるツールだ。下で矛盾してる部分がピックアップされているので右のボタンから選択することができる。では今回はremote青を選択してみよう。
選択が済んだら以下のようにp4mergeツールを終了させる。
win
閉じるボタンを押す
ボタンがでるのでsave
mac
command+s で保存して command +q で画面を閉じる
すると再びターミナルに戻るのでadd & commitをしてmergeが完了する。
実際のコマンドは以下
$ git add .
$ git commit -m"コンフリクト発生。xの値は-5を採用"
以上がUnity開発の際にCONFLICTが発生してしまったときの解消方法だ。
状況に合わせて使いこなしていくとよいだろう。
今回はUnityプロジェクト自体が極めてシンプルだったが簡単だったがこれが複雑になってくるとCONFLICTを解消していくのが難しくなっていく。なのでUnity開発の際、まめにcommitを行ってcommit粒度を下げていくことがスムーズな開発の基本となる。
また、Unity開発時のCONFLICT要因の一つにUnityで最後に行った作業を保存せずにcommitしてしまうというのがある。ターミナルに戻る前にかならずCTRL+Sでプロジェクトを保存することが大切だ。
コメント