(O+P)ut

アウトプット



(O+P)ut

エンジニアのアウトプット

【Git】マージ時のコンフリクトを解決する流れ

スポンサーリンク

はじめに

Gitではブランチを分けて独立しながら開発することが可能ですが、同一箇所を修正した場合はマージをする際に検知する機能が存在しています。

本記事では同一箇所を修正してコンフリクトが発生する流れをローカルの個人環境であえて発生させ、どのように解決するのかの流れを追う手順を用意しました。Gitの勉強を始めたての方には参考になると思います。

環境情報
$ git --version
git version 2.21.0

conflictを発生させる

以下のようなテスト用ファイルを用意します。

$ cat test.sh
#!/bin/bash

echo hello
echo world

この状態で初期コミットを行い

$ git init
Initialized empty Git repository in /…/.git/

$ git add test.sh

$ git commit -m "first commit"
[master (root-commit) 0dcb9b4] first commit
 1 file changed, 4 insertions(+)
 create mode 100755 test.sh

ブランチをtestというものに分けて内容を一部修正してコミットします。

$ git branch
* master

$ git branch test

$ git checkout test
Switched to branch 'test'

$ sed -i -e "s/hello/goodbye/" test.sh

$ git add test.sh

$ git commit -m "fix 1"
[test 4e71e99] fix 1
 1 file changed, 1 insertion(+), 1 deletion(-)

今のコミットログは以下のような感じ。masterをベースに修正したもの(fix1)がtestとなっています。

$ git log --all --graph --pretty=oneline
* 4e71e9929d65f544d020e8b351e604a06201b97d (HEAD -> test) fix 1
* 0dcb9b4c07a8ff086a7e4d539aebbbef05e45c00 (master) first commit

ここでコンフリクトを起こすためにmaster側の同一箇所を修正します。

$ git checkout master
Switched to branch 'master'

$ cat test.sh
#!/bin/bash

echo hello
echo world

$ sed -i -e "s/hello/Hello/" test.sh

$ git add test.sh

$ git commit -m "fix 1'"
[master ad98679] fix 1'
 1 file changed, 1 insertion(+), 1 deletion(-)

コミットログを見ると枝分かれが発生していることが確認できます。

$ git log --all --graph --pretty=oneline
* ad98679e2016ef97c60aeb95da8aa80c09034249 (HEAD -> master) fix 1'
| * 4e71e9929d65f544d020e8b351e604a06201b97d (test) fix 1
|/
* 0dcb9b4c07a8ff086a7e4d539aebbbef05e45c00 first commit

ここで、マージ作業を行おうとすると「CONFLICT (content): Merge conflict in test.sh」という文言でエラーとなります。

$ git merge test
Auto-merging test.sh
CONFLICT (content): Merge conflict in test.sh
Automatic merge failed; fix conflicts and then commit the result.

conflictの発生個所の特定及び修正

該当のファイルを確認すると以下のように書き換わっています。

#!/bin/bash

<<<<<<< HEAD
echo Hello
=======
echo goodbye
>>>>>>> test
echo world

これはエディタの見え方が変わっているわけではなく、git merge時にテキスト自体に挿入されています

なのでスクリプトとして実行しようとすると下記のように失敗します。

$ ./test.sh
./test.sh: 行 3: 予期しないトークン `<<<' 周辺に構文エラーがあります
./test.sh: 行 3: `<<<<<<< HEAD'

競合した箇所を確認しながら不要の箇所を消して以下のように正しい修正を残したうえで

$ cat test.sh
#!/bin/bash

echo Hello
echo world

再度コミットを行えば

$ git add test.sh

$ git commit -m "merge testbranch"
[master a2ba16a] merge testbranch

以下のようにマージが完了します。

$ git log --all --graph --pretty=oneline
*   a2ba16a8017cc0a31c0ffe3d8946518d7dfe49ed (HEAD -> master) merge testbranch
|\
| * 4e71e9929d65f544d020e8b351e604a06201b97d (test) fix 1
* | ad98679e2016ef97c60aeb95da8aa80c09034249 fix 1'
|/
* 0dcb9b4c07a8ff086a7e4d539aebbbef05e45c00 first commit

ちなみにコンフリクトが発生なければ「Merge branch 'test'」というコミットメッセージが付与されて統合されます。

終わりに

ブランチ間で「同一ファイルの同一箇所を異なる修正」を行うとGitは自動的にそれを検出してユーザ側に知らせてくれます。
個人で利用しているとなかなか発生しにくい事象ですが、一度上記手順のように動き方を確認しておくと良いと思います。

以上、ご参考になれば幸いです。