未来エンジニア養成所Blog

月単価180万以上のプログラミング講師がプログラミングを皆に楽しんでもらうための情報をお届けします。

【Git&GitHub】コンフリクトの解決

title


コンフリクトを解決しよう

今回は最後のマージの種類のコンフリクトについて解説します。


コンフリクトとは何かというと、複数人の人が同じ箇所で別々の変更をしてしまった時に、どの変更を優先したら良いか分からないという状態のことを「コンフリクト」と言います。


今回見ていくのは、コンフリクトの解決のやり方についてです。


ではコンフリクトとはどのようなときに起こるのでしょうか。

これはほぼ先ほど書いたようなものですが、同じファイルの同じ行に対して複数人が異なる編集を行った時に起こります。


ではそれをイメージで確認していきましょう。

いつもと同じようにmainブランチとfeatureブランチがありました。

mainブランチとfeatureブランチそれぞれでindex.htmlの5行目を変更したとします。

その変更内容が、同じ箇所を変更しているけど、別々の変更を行ったとします。

コンフリクト


その状態でmainブランチにfeatureブランチの内容を取り込もうとして、「git merge feature」コマンドを実行しました。


すると何が起こるかというと、マージしようとした結果コンフリクトが発生します。

なぜコンフリクトが発生するかというと、index.htmlの5行目にある同じ変更を行われた箇所をmainブランチの内容を優先したいのか、featureブランチの内容を優先したいのかgitは判断できないのです。

その判断できない状況がコンフリクトです。

コンフリクト発生


ではコンフリクトが起きたらどのようにすれば良いのでしょうか。

ここからはそのコンフリクトの解決の方法について見ていきます。


コンフリクトすると何が起こるかというと、コンフリクトしたファイル(今回ですとindex.html)の内容は次に記載されているような内容になっています。

<h1>Gitチュートリアル</h1>
<p>ようこそ</p>
<<<<<<< HEAD
<p>git addについて学ぼう</p>
=======
<p>git commitを知ろう</p>
>>>>>>> feature

ここで注目して欲しいのは、まず3行目の「<<<<<<< HEAD」と記載されている部分です。

その後に「<p>git addについて学ぼう</p>」というのがあって、5行目に「=======」と書かれています。

この部分は何かというと、HEADに元々記載されていた内容(HEADとは自分が作業していたブランチなので今回はmainブランチ)には「<p>git addについて学ぼう</p>」と記載されていたということがここに記されています。


次に注目して欲しいのは、5行目の「=======」から7行目の「>>>>>>> feature」で囲われている部分です。

今回だと「<p>git commitを知ろう</p>」と書かれている部分は、featureブランチに元々書かれていた内容になります。


このようにコンフリクトすると、コンフリクトした箇所に自分の今の作業ブランチの内容と、マージしてきたブランチの内容それぞれがこのように書かれています。


ではここからどのようにしてしたら良いのでしょうか。

それは次のように、最終的なファイル内容をそこに記載すればOKです。

<h1>Gitチュートリアル</h1>
<p>ようこそ</p>
<p>git addについて学ぼう</p>
<p>git commitを知ろう</p>


具体的な手順としてはまず2つあって、1つ目がファイルの内容を書き換えることです。

ここで最終形をどのようにしたら良いか、ファイルの内容をここに記載していきます。


2つ目が最初の例で言う3行目と5行目と7行目の記述を削除することです。

そして最終的に綺麗なファイルの内容を記載します。


このようしてから保存すればコンフリクトは解消します。


実際にやってみよう

では実際に確認していきましょう。


今回mainブランチの「index.html」ファイルと、featureブランチの「index.html」ファイルそれぞれに変更を加えて、その内容をコンフリクトさせていきます。


ではまず、エディタを開いて「index.html」ファイルを編集していきましょう。

今回は「<p>コンフリクト</p>」と追記します。

ターミナルで変更内容をコミットしていきます。

$ git add index.html

$ git commit -m 'コンフリクトを追記'
[main 1b494f5] コンフリクトを追記
 1 file changed, 1 insertion(+)


次にfeatureブランチの方に修正を加えて見ましょう。

「git checkout feature」としてfeatureブランチに切り替えていきます。

$ git checkout feature
Switched to branch 'feature'


ではfeatureブランチのindex.htmlに変更を加えていきましょう。

こちらには「<p>conflict</p>」と書いてみましょう。

保存したらコミットします。

$ git add index.html

$ git commit -m 'conflictを追記'
[feature 5b7fc4e] conflictを追記
 1 file changed, 1 insertion(+)


ではmainブランチに切り替えてfeatureブランチの内容をマージしていきます。

$ git checkout main
Switched to branch 'main'

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


するとコンフリクトが起きたということが表示されます。

そしてコンフリクトが起きた結果、AutoMergeが失敗したよと表示されています。


では、どのファイルがコンフリクトが起きているかをどのように確認するのかというと、「git status」コマンドを使っていきます。

 $ git status
On branch main
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.html

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


「git status」コマンドを使うと「both modified: index.html」と記載されています。

これはつまり「index.html」に対して、両方が変更を加えたよと、つまりコンフリクトしているよと言うのを表しています。


ではここからコンフリクトを解決していきましょう。

テキストエディタで「index.html」を開きます。

<h1>Gitチュートリアル</h1>
<p>git status</p>
<p>git diff</p>
<p>git commit --amend</p>
<<<<<<< HEAD
<p>git merge</p>
<p>コンフリクト</p>
=======
<p>conflict</p>
>>>>>>> feature


するとこのように5行目に「<<<<<<< HEAD」というのがあって、8行目に「=======」、10行目に「>>>>>>> feature」と書かれています。

この5行目から8行目の部分つまり6行目と7行目の部分の内容がHEADに書かれていた内容、つまり今自分がいるブランチであるmainブランチの内容がここ書かれています。

この8行目から10行目に書かれている部分、つまり9行目の部分にはfeatureブランチで書かれていた内容が書かれています。


今回は最終的に6行目の「git merge」という内容と、10行目の「conflict」という内容を記載したいと思います。

いらない部分については削除します。

<h1>Gitチュートリアル</h1>
<p>git status</p>
<p>git diff</p>
<p>git commit --amend</p>
<p>git merge</p>
<p>conflict</p>


これで「index.html」のファイルの内容を綺麗にすることができました。

これを保存して、ターミナルに戻ります。

もう一度「git status」で状況を確認してみます。

$ git status
On branch main
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.html

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


変わらず、「index.html」がコンフリクトしているよと書かれています。

このコンフリクト分の内容をコミットしていきましょう。

$ git add index.html

$ git commit -m 'コンフリクトの解決'
[main c5c1db0] コンフリクトの解決

これでコミットができました。


このようにコンフリクトしてもファイルの内容をもう一度綺麗にしてあげれば、コンフリクトは解決できます。

良くコンフリクトしてしまうと、いま何が起きているのか分からなくなった、と混乱してしまうのですが、特に混乱する必要はありません。

落ち着いて最終的にどのようなファイル内容にしたいのかというのを先に記載して、その後にコンフリクト内容が記載されている特別な記号等を削除して、綺麗に整えてあげればコンフリクトは解決できます。

今後もしコンフリクトしたとしても、落ち着いて解決していきましょう。


参考図書



独学で挫折しそうになったら、オンラインプログラミングスクール
未来エンジニア養成所Logo



あわせて学習したい

phoeducation.work