【Git】コンフリクトの解消と発生原因とは?マージの中止方法
この記事からわかること
- Gitのコンフリクトの解消方法
- コンフリクトの発生原因
- マージをキャンセルするには?
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
GitのConflict(コンフリクト)とは?
Conflict(コンフリクト)とは「衝突」を指す英単語 でありGitではブランチをマージする際に互いの変更点が重なってしまうことを指します。これによりマージは失敗し、対象ファイルには衝突箇所が記され、Gitの状態はマージ途中のまま開発者からの解消またはキャンセルを待っている状態になります。
コンフリクトが発生する原因は同じファイルの同じ行同士が、別ブランチのコミットで変更されている場合です。なのでブランチ1が「Aファイルの2行目」を、ブランチ2が「Aファイルの3行目」を変更していただけであればコンフリクト発生しません。
しかしブランチ1が「Aファイルの2行目」を、ブランチ2も「Aファイルの2行目」を変更していた場合、コンフリクトが発生しマージは失敗します。
コンフリクトの原因箇所を特定する
コンフリクトが発生している対象ファイルはgit merge
コマンドを実行時に、以下のように表示されます。(以下はpendingブランチをマージして際に「ArtistList.txt」でコンフリクトを起こした様子)
$ git merge pending
Auto-merging ArtistList.txt
CONFLICT (content): Merge conflict in ArtistList.txt
Automatic merge failed; fix conflicts and then commit the result.
まあコンフリクトが起こっている箇所は対象のファイル内に以下のような記号で追記されます。
●ROCKFES 出演アーティスト
1.ONE OK ROCk
2.My First Story
<<<<<<< HEAD
3.Saucy Dog
=======
3.Aimer
>>>>>>> pending
上記の記号の意味は以下の通りです。
<<<<<<< HEAD
// HEADがあるブランチ側の変更内容
=======
// マージするブランチ側の変更内容
>>>>>>> pending
コンフリクトを解消する方法
コンフリクトを解消する方法は至ってシンプルで手動でファイルを書き直し再度コミットするです。コンフリクトは同じ行に異なる変更が起きてしまい、Git側がどちらを優先するべきか困っている状況なので、手動で対象ファイルの該当行を書き直し、ステージング後、コミットすることでコンフリクトが解消されマージが完了します。
マージを中止する
コンフリクトが発生した場合はマージ途中なので何かしらの対処をしないと元の状態に戻りません。解消が不可能な場合はマージ自体を中止することでマージ前の状態に戻すことが可能です。
中止させるにはgit merge --abort
コマンドを実行します。「abort」は日本語で「中断する」といった意味を持つ英単語です。
$ git merge --abort
コンフリクトを実際に起こしてみる
実際にマージの際にコンフリクトが発生するようにしてみます。今回は「ROCKFES」というプロジェクトを作成し、その中に「ArtistList.txt」で出演アーティストを管理してみたいと思います。(勝手にアーティストの名前使ってすみません。。)
- プロジェクトの作成&Gitの初期化
- ArtistList.txtの作成と編集
- ステージング&コミット
- ArtistList.txtに追記〜コミット
- 主ブランチを進める
- ブランチを切り替える
- pendingブランチを進める
- マージしてみる(コンフリクトの発生)
- コンフリクトを解消する
ブランチの作成や切り替えについては以下の記事を参考にしてください。
1.プロジェクトの作成&Gitの初期化
まずはプロジェクトを作成しGitの管理下に置きます。
$ mkdir ROCKFES
$ cd ROCKFES
$ git init
Initialized empty Git repository in /Users/username/Desktop/ROCKFES/.git/
2.ArtistList.txtの作成と編集
touch
コマンドで「ArtistList.txt」を作成し、中に内容を記述します。
$ touch ArtistList.txt
●ROCKFES 出演アーティスト
3.ステージング&コミット
ステージングとコミットを行います。
$ git add ArtistList.txt
$ git commit -m "ArtistListの作成"
[main (root-commit) 9e1867b] ArtistListの作成
1 file changed, 1 insertion(+)
create mode 100644 ArtistList.txt
4.ArtistList.txtに追記〜コミット
続いて「ArtistList.txt」を編集し再度、ステージング&コミットしておきます。
●ROCKFES 出演アーティスト
1.ONE OK ROCk
2.My First Story
$ git add ArtistList.txt
$ git commit -m "出演アーティスト2組の追加"
[main 851e662] 出演アーティスト2組の追加
1 file changed, 4 insertions(+), 1 deletion(-)
5.ブランチの作成
ここで新しいブランチを作成しておきます。ブランチ名は「pending」としておきました。ここでの想定はほぼ確定だけどスケジュール調整待ちみたいな感じです。(この想定がブランチを切り分ける意味)
$ git branch pending
$ git branch -v
* main 851e662 出演アーティスト2組の追加
pending 851e662 出演アーティスト2組の追加
この状態では2つのブランチが同じコミットを参照しています。
6.主ブランチを進める
ここでさらに出演が確定したアーティストが出たのでmain
ブランチを進めてみます。「3.Saucy Dog」を追記しました。
●ROCKFES 出演アーティスト
1.ONE OK ROCk
2.My First Story
3.Saucy Dog
ステージング&コミットです。
$ git add ArtistList.txt
$ git commit -m "Saucy Dogの追加"
[main bc5d1ec] Saucy Dogの追加
1 file changed, 2 insertions(+), 1 deletion(-)
これで今こんな感じです。main
は3つのコミット履歴を持つブランチに、pending
は2つのコミット履歴を持った状態です。
7.ブランチを切り替える
ここでブランチを切り替えてみます。
$ git checkout pending
Switched to branch 'pending'
この状態でワークツリーの「ArtistList.txt」を開いてみると2回目のコミット時の中身(以下のよう)になっています。
●ROCKFES 出演アーティスト
1.ONE OK ROCk
2.My First Story
8.pendingブランチを進める
ではこの状態で「ArtistList.txt」を編集していきます。
●ROCKFES 出演アーティスト
1.ONE OK ROCk
2.My First Story
3.Aimer
ステージング&コミットです。
$ git add ArtistList.txt
$ git commit -m "Aimerの追加"
[pending dd4425c] Aimerの追加
1 file changed, 2 insertions(+), 1 deletion(-)
ここで一度ブランチとコミットの状況を確認してみます。pending
ブランチが進んで枝分かれしているのが確認できます。
$ git log --all --graph --oneline
* dd4425c (pending) Aimerの追加
| * bc5d1ec (HEAD -> main) Saucy Dogの追加
|/
* 851e662 出演アーティスト2組の追加
* 9e1867b ArtistListの作成
9.マージしてみる(コンフリクトの発生)
ではmain
とpending
をマージしてみます。(Aimerの出演が確定しました)まずはブランチを主軸に切り替えてマージを実行します。
$ git checkout main
Switched to branch 'main'
$ git merge pending
Auto-merging ArtistList.txt
CONFLICT (content): Merge conflict in ArtistList.txt
Automatic merge failed; fix conflicts and then commit the result.
ここで「ArtistList.txt」を開いてみると以下のようにコンフリクトを起こしている箇所が分かるようになっています。コンフリクトがない場合はここで正常に完了し、2つの変更が併合されます。今回は同じ行部分(2.2.My First Storyの下側)を編集していたためコンフリクトが発生しています。
●ROCKFES 出演アーティスト
1.ONE OK ROCk
2.My First Story
<<<<<<< HEAD
3.Saucy Dog
=======
3.Aimer
>>>>>>> pending
ちなみにこの状態で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: ArtistList.txt
no changes added to commit (use "git add" and/or "git commit -a")
10.コンフリクトを解消する
コンフリクトは手動で「ArtistList.txt」を書き換えて解消します。以下のように正しいファイルに書き換えたら、このファイルをステージングします。
●ROCKFES 出演アーティスト
1.ONE OK ROCk
2.My First Story
3.Saucy Dog
4.Aimer
これでコンフリクトが解消され2つのブランチをマージすることができました。最後に変更をコミットして完了です。
$ git commit -m "pendingのマージ"
[main 817afac] pendingのマージ
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。