Git でのマージの競合を解決する

Azhar Bashir Khan 2022年2月6日
Git でのマージの競合を解決する

このチュートリアルでは、Git で 2つのブランチをマージするときに発生する競合を解決する方法を示します。

通常、共同作業環境では、異なるチームメンバーが同じファイルに対して作業を行うことがよくあります。たとえば、ある機能の開発に取り組んでいる 1 人のチームメンバーが、README ファイルを編集して、開発された機能に関する情報を提供する場合があります。

バグの修正に取り組んでいる別のチームメンバーが、同じ README ファイルに修正されたバグに関する情報を追加する場合があります。彼らは異なるブランチで作業していて、それぞれのブランチで変更をコミットしている可能性があります。

ときどき、まとまりのあるビルドを提供するために、さまざまなブランチをマージする必要があります。したがって、同じファイルが異なるブランチで更新されると、この操作によってマージの競合が発生します。

次に、競合を解決し、変更をマージする必要があります。これを例を挙げて説明します。

git mergetool を使用して 2つのブランチをマージするときに発生する競合を解決する

マージの競合を解決する前に、Git で使用される diff ツールを次のように設定する必要があります。

$ git config merge.tool meld
$ git config merge.conflictstyle diff3
$ git config mergetool.prompt false

上記のコマンドは、デフォルトの差分ツールとして meld を設定します。また、conflictstylediff3(つまり)に設定しました。これにより、diff ツールが両方のファイル(現在のブランチ 1 とマージ元のブランチ内の 1つ)の共通の祖先を表示するように設定されます。

サポートされているさまざまな差分ツールを表示するには、次のコマンドを実行します。

$ git mergetool --tool-help

ここで、競合を解決する方法を示す例から始めます。次のように 2つのブランチがあるとしましょう。

$ git branch
* main
  feature1

最初のブランチは main ブランチで、2 番目のブランチは feature1 という名前の機能開発ブランチです。

main ブランチに次のような内容の README.md ファイルがあります。

$ cat README.md
# Upwork
Upwork projects

上に示したように、現在は main ブランチにいます。次に、feature1 ブランチに切り替えます。

$ git checkout feature1
Switched to branch 'feature1'

$ git branch
  main
* feature1

README.md を更新し、その内容を次のように表示します。

$ cat README.md
This is conflicting branch line.

次に、main ブランチを feature1 ブランチとマージして、そのブランチの最新の変更を取得します。

マージ中、Git は次のようにマージの競合を示します。

$ git merge main
Auto-merging README.md
CONFLICT (add/add): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.

紛争に関する詳細情報は、次のように入手できます。

$ git status
On branch feature1
You have unmerged paths.
  (fix conflicts and run "git commit")

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

	both added:      README.md

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

競合のあるファイル README.md の内容を出力します。

$ cat README.md 
<<<<<<< HEAD
This is conflicting branch line.

||||||| merged common ancestors
=======
# Upwork
Upwork projects
>>>>>>> main

ファイルにさまざまな記号が表示されます。

また、<<<<<<< の後に HEAD が続く記号は、現在のブランチのエイリアスです。これは、このセクション内の編集の開始を示します。

記号 ======= は、現在のブランチ内のリビジョンの終わりと新しいブランチ内の編集の始まりを示します。

記号 >>>>>>> の後にリモートブランチ名が続きます。main は、試行されたマージが発生した場所を示します。

次に、mergetool を使用して競合を解決します。

$ git mergetool
Merging:
README.md

Normal merge conflict for 'README.md':
  {local}: created file
  {remote}: created file

これにより、meld が起動します(これをデフォルトの差分ツールとして設定したため)。下の画像を参照します。

git-mergetool-meld1

左側のペインには、ローカルブランチで行われたファイル README.md の編集が表示されます。中央のペインには、競合を解決するために行われた変更の結果が含まれています。右側のペインには、リモートブランチで行われた編集が表示されます。main(つまり)マージするブランチ。

ローカルとリモートの両方の変更を保持するか、どちらか一方を保持するかを選択できます。次のように、リモートブランチの変更を保持することを選択します。

git-mergetool-meld2

次に、meld ツールを保存して終了します。

README.md ファイルを出力して、更新を確認します。

$ cat README.md
# Upwork
Upwork projects

ここで、Git への変更をコミットします。

$ git commit -m "merged from main"
[feature1 3c39d7b] merged from main

次に、git diff コマンドを実行して、feature1 ブランチと main ブランチ間の競合をチェックします。

$ git diff feature1 main

feature1 ブランチのステータスを確認します。

$ git status
On branch feature1

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	README.md.orig

マージ中に mergetool によって作成された 1つのファイル README.md.orig が表示されます。

次のコマンドを実行して削除します。

$ git clean -f

したがって、Git の mergetool を使用して 2つのブランチをマージする際の競合を正常に解決しました。

関連記事 - Git Merge