開発ブログ

WWWクリエイターズが送る、Git、CSS、HTML、コマンドライン、Macの便利機能など、開発に関する役立ち情報発信します。気まぐれに更新。

git mergeでの競合(コンフリクト)の解決方法のまとめ。

最終更新:2017-07-05 by Joe

git merge のコンフリクトの解決方法についてです。

gitでブランチを利用し、git mergeを使うようになったら、競合(コンフリクト)とその解決の作業を避けて通れません。

git mergeについて

まず、git mergeについてです。

git merge は、現在のブランチに対して、特定のコミットまでの歴史を統合します。実際の使用では、しばしばブランチ名を指定します。ブランチ名は、そのブランチの先頭コミットへの「参照」ですので、実際に指定されるのはコミットです。

// branchを現在のブランチにマージする
git merge <branch>

具体的には、例えば、下記のマスターブランチ「G」に対して、topicブランチをマージすると・・・

	  A---B---C topic
	 /         
    D---E---F---G master

// masterに、topicブランチをマージする
git merge topic

このように、新しいコミットを「H」が結果として生成されます。A、B、Cにおける変更が、masterブランチに取り込まれます。

	  A---B---C topic
	 /         \
    D---E---F---G---H master

コンフリクトの発生

変更内容をマージにより統合する際に、もし同じファイルの重複する部分が変更されていると、変更同士が衝突し「コンフリクト」と呼ばれる状態を引き起こします。

// マージの実行
$ git merge branch-B

// コンフリクトによる中断
Auto-merging index.php
CONFLICT (content): Merge conflict in index.php
Automatic merge failed; fix conflicts and then commit the result.

2つの履歴のうち、どっちらのコード変更を採用すればいいの?という問題を、Git自身が決めることはできないので、開発者が指定したり、次コードを調整したりする必要があるのです。

git mergeの実行時に、コンフリクトが起きると、git mergeの処理は一時停止され、開発者にその後の処理を委ねます。これはGit において特別な状態で「merge の中断状態」となります。この時、開発者はいずれかを選択することになります。

  • コード上のコンフリクトを解決して、git commit の実行により、マージコミットをコミットする
  • いったんマージを中止して元に戻す

上記のいずれかの手段を行う以外は、他の Git 操作ができません。

コンフリクトの解消方法

それでは、解決を試みます。

[1] 競合している箇所の確認する

「git status」を行えば、コンフリクトの箇所が分かります。

// ステータスを確認
$ git status

On branch branch-A
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)

	both modified:   index.php

no changes added to commit (use "git add" and/or "git commit -a")

Unmerged path に、コンフリクトが発生したファイルが列挙されています。

[2] 必要箇所を修正する

コンフリクトしているファイルが分かったら、直接ファイルを開いて修正していきます。ファイル内で、コンフリクト箇所は「<<<< HEAD」「====」「 >>>> topic」によってハイライトされていますので、ファイル内で「>>>>」などの連続を検索すると、問題の箇所がすぐに見つかるでしょう。

<div class="content-area front">

<<<<<<< HEAD
  <h1>This is added from branch-A</h1>
=======
  <h1>This is added from branch-B</h1>
>>>>>>> branch-B

慣れていないとちょっとぎょっとしますが、恐れる事はありません。HEADが、現在のブランチです。その下が「git merge branch-B」 と対象に指定したブランチです。

これらはコード的にも成立しないので、エディタで、不要な部分を消して綺麗に整えます。

[3]コミットしなおす

コンフリクトしたすべてのファイルを慎重に修正して、git add します。

$ git add index.php

status を確認します。

$ git status

// 出力
On branch branch-B
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Changes to be committed:

	modified:   index.php

Gitが「All conflicts fixed but you are still merging.」と言っています。

あなたがコンフリクトを解消して、git add を実行して、修正をインデックスにステージした事に気づいています。あとは、git commit を実行すれば、競合を解決したマージコミットの完成です。

$ git commit

// エディタでメッセージを編集・・
Merge branch 'branch-B' into branch-A

# Conflicts:
#       index.php
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
#       .git/MERGE_HEAD
# and try again.

無事、マージコミットが作成されました。

*   2787f68 (HEAD -> refs/heads/branch-A) Merge branch 'branch-B' into branch-A
|\  
| * 9e2f7d0 (refs/heads/branch-B) fix something again.
* | 733fc68 fix something.
|/  
* 1034887 (refs/heads/master) Update something again. 
* 9031694 Update something.

 

以上、git merge のコンフリクトの解決についてでした。

参考リンク

 

閉じる