2017年08月03日

git コンフリクトに対処する

ブランチをマージした。
git_conflict01.png
$ git merge new_branch 
Auto-merging mystyle.css
CONFLICT (content): Merge conflict in mystyle.css
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
2つのファイルでコンフリクトが発生した。

コンフリクトした"index.html"ファイルの中身を見てみる。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>git確認</title>
</head>
<body>
<p>master branch</p>
<<<<<<< HEAD
<p>modified master</p>
=======
<p>new_branch</p>
>>>>>>> new_branch
</body>
</html>
gitでは現ブランチの内容と、マージするブランチの内容とでどちらを採用したらいいか判断がつかないときに、この操作を行った人にマージ対応を求めている状態がコンフリクト。


このときコンフリクトしたファイルの中には、コンフリクトした箇所がマーカーで示されている。
<<<<<<< HEAD
"現ブランチのコンフリクト部分"
=======
"マージするブランチのコンフリクト部分"
>>>>>>> マージするブランチ名

このマーカーで示された箇所を処理してあげないとコンフリクトは解消されない。
エディタを開き、このマーカー部分を修正して、再度コミットすればいい。




diffツール


GUIが使えるのであれば、コンフリクトを解消するときにGUIツールで作業したほうが直感的に作業できて便利。meld, KDiff3などいくつかツールがあるが、ここでは P4Merge というツールがあるので使ってみる。



インストール


ここからダウンロードする。

[DOWNLOAD] をクリックしする。
git_conflict02.jpg

OSを選んでダウンロードする。
git_conflict03.jpg

ユーザ登録の画面が表示される。登録しない場合はskipすることもできる。
git_conflict04.jpg

"p4v.tgz" ファイルがダウンロードされる。


ダウンロードが完了したら、ダウンロードしたファイルのディレクトリで展開する。
$ tar -xzvf p4v.tgz

展開されたディレクトリを移動し、シンボリックリンクを設定する。
$ sudo mv p4v-2017.2.1535556/ /opt/
sudo ln -s /opt/p4v-2017.2.1535556/bin/p4merge /usr/local/bin/p4merge




mergetoolに設定


configファイルに設定を行う。

$ git config --global merge.tool p4merge


マージツールを使う際のオプションも設定しておく。

$ git config --global mergetool.p4merge.cmd 'p4merge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"'
$ git config --global mergetool.p4merge.trustExitCode false
$git config --global mergetool.p4merge.keepTemporaries false
$ git config --global mergetool.keepBackup false


"cmd" :p4mergeを実行する方法を指定
$BASE共通箇所の内容を保持する一時ファイルのパス
$LOCAL現ブランチの内容を保持する一時ファイルのパス
$REMOTEマージするブランチの内容を保持する一時ファイルのパス
$MERGEDマージ結果を書き出すファイル(コンフリクトしたファイル)

"trustExitCode" :p4mergeの終了コードでマージが成功したかどうかを判断できるのかどうか→"false" できないとした。
"keepTemporaries" :マージ作業の一時ファイルを残すのかどうか→"false" は自動的に削除される。
"keepBackup " :マージが完了したときに、バックアップファイル(*.orig)が残される→"false" は自動的に削除される。

"~/.gitconfig" ファイルに直接に記述してもいい。
.....

[merge]
tool = p4merge
[mergetool "p4merge"]
cmd = p4merge \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"
keepBackup = false
trustExitCode = false
keepTemporaries = false
[mergetool]
keepBackup = false




mergetoolを起動


コンフリクトした後、マージツールを起動する。

$ git mergertool


gitは "config" に設定された "merge.tool" を探し、起動する。
git_conflict05.jpg
"p4Merge" は4ペイン表示。
上部3つが左側から、"$LOCAL" "$BASE" "$REMOTE" と並び、下部が "$MERGED" となる。


下部のペインの左側にマーカーがあり、上部のペインにも同じマーカーが付けてある。
同じマーカーで "$LOCAL" "$BASE" "$REMOTE" を示しており、下部のマーカーをクリックすることでどの内容をマージで採用するかを決定できる。
複数の内容を有効としたければ、Shift + クリック することで複数採用することが可能。
git_conflict06.jpg

マージが完了すれば、保存終了する。
複数のコンフリクトがある場合、終了したら次のファイルのマージ処理が起動してくる。

2つのファイルのコンフリクトがあったので、2回ツールが起動し、マージ処理を行った。
$ git mergetool 
Merging:
index.html
mystyle.css

Normal merge conflict for 'index.html':
{local}: modified file
{remote}: modified file
QString::arg: 1 argument(s) missing in %1 - %2

Normal merge conflict for 'mystyle.css':
{local}: modified file
{remote}: modified file
QString::arg: 1 argument(s) missing in %1 - %2

"QString::arg: 1 argument(s) missing in %1 - %2" 良くわからないエラーがあるが、ツール起動に影響はないので放置している。。。

すべてマージが完了すれば、ステージして、コミットする。




まとめ


マージツールを使うと直感的に採用したい変更が決定しマージできるので、GUIを使っているのであればコンフリクトの解消にはぜひに使ったほうがいい。同じファイルに複数のコンフリクトがある場合や、ときにはgit側で共通部分の判別がつかず、大きなブロックで差分がでてしまうこともある。このような場合には、ツールで全体を見ながら修正できたほうが安心できる。






gitをインストール
gitサーバーのセットアップ
git ブランチについて
git 変更を一時的に退避 stash
git ブランチを合流するマージ
git ブランチを付け替える
git コミット履歴を変更する
git 変更をリセットする
git リモートでの操作
git ファイルの追跡
git リリース準備
git リモートブランチを追加
git チェックアウトをもっと便利に使う
git プロジェクトの構成
git 変更をpatchファイルにする
git 失敗したときの復元
posted by Zorinos at 20:00| Comment(0) | Linux | 更新情報をチェックする