こんにちは ECF Tech
ブログ担当 Michiです。
Gitシリーズ第6回はコンフリクト編です。よろしくお願いします。
本記事は「Gitを使ってみよう!」というシリーズで作成している記事の1つになります。下記のリンクより、第1回からの記事を閲覧できます。ご活用ください。
対象読者
- Gitを学んでみたい方
- Gitのクローンやコミットをやったことがある方
今回から複数のプログラマーによる開発がスタートします。そんな中、Gitがどんな風に活躍するかを見ていきたいと思います。
まずは新規に、Cドライブ直下にwork02
というフォルダを作成し、クローンします。
コマンド
C:\work02>git clone https://github.com/MichiharuT/hello_repo.git
クローンできていることを確認します。
C:\work02>cd hello_repo C:\work02\hello_repo>dir ドライブ C のボリューム ラベルは OS です ボリューム シリアル番号は 6063-1083 です C:\work02\hello_repo のディレクトリ 2019/09/22 11:17 <DIR> . 2019/09/22 11:17 <DIR> .. 2019/09/22 11:17 124 program01.txt 2019/09/22 11:17 30 program02.txt 2019/09/22 11:17 47 readme.txt 3 個のファイル 201 バイト 2 個のディレクトリ 169,050,136,576 バイトの空き領域 C:\work02\hello_repo>
ここが新しいプログラマBさんの作業フォルダだとします。現在の状態を図にすると、次のようになります。
それではprogram02.txtを開いて作業を行ないます。次のようにします。
表示するための機能A 表示するための機能B
表示するための機能Bができましたので、コミットしましょう。git add
コマンド、git commit
コマンドの順で実行します。
C:\work02\hello_repo>git add . C:\work02\hello_repo>git commit -m "表示する機能Bを追加" [master 5c646b6] 表示する機能Bを追加 1 file changed, 2 insertions(+), 1 deletion(-) C:\work02\hello_repo>
コミットが完了しました。
表示するための機能Bを作成したBさんは、そのままリモートリポジトリにPushすることにしました。
git push origin master
一方でAさんが同じprogram02.txtに対し、別の機能を追加していたとしましょう。
次のコマンドでC:\work01\hello_repo
に移動します。
C:\work02\hello_repo>cd C:\work01\hello_repo
program02.txtを開き、次のようにします。
表示するための機能A 表示するための機能C
機能Cの追加が終わりましたので、コミットしましょう。
C:\work01\hello_repo>git add . C:\work01\hello_repo>git commit -m "表示するための機能Cを追加" [master 0722b84] 表示するための機能Cを追加 1 file changed, 2 insertions(+), 1 deletion(-)
コミットが完了しました。
AさんもリモートリポジトリへPushすることにしました。git push
コマンドを実行します。
C:\work01\hello_repo>git push origin master
実行結果
To https://github.com/MichiharuT/hello_repo.git ! [rejected] master -> master (fetch first) error: failed to push some refs to 'https://github.com/MichiharuT/hello_repo.git' hint: Updates were rejected because the remote contains work that you do hint: not have locally. This is usually caused by another repository pushing hint: to the same ref. You may want to first integrate the remote changes hint: (e.g., 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details. C:\work01\hello_repo>
リモートリポジトリへのpushに失敗しました。理由はリモートリポジトリへ統合(マージ)する際に競合(Conflict)が発生してしまったためです。
競合とは、ファイルを編集した箇所が他の作業者と重複してしまい、うまくマージできない状態の事を言います。
Aさんが作成した機能もBさんが作成した機能も今回のプログラムには欠かせない機能なので、「表示するための機能B」と「表示するための機能C」の両方がprogram02.txtに入るように、ファイルを手直しする必要があります。この作業を競合の解決といいます。
手直しするためには、一旦リモートリポジトリの内容をローカルリポジトリに持ってくる必要があります。この操作をPullといいます。次のコマンドを実行しましょう。
git pull
実行結果
remote: Enumerating objects: 5, done. remote: Counting objects: 100% (5/5), done. remote: Compressing objects: 100% (3/3), done. remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0 Unpacking objects: 100% (3/3), done. From https://github.com/MichiharuT/hello_repo b783e81..5c646b6 master -> origin/master Auto-merging program02.txt CONFLICT (content): Merge conflict in program02.txt Automatic merge failed; fix conflicts and then commit the result. C:\work01\hello_repo>
メッセージ下部にCONFLICT
と表示されています。program02.txtを自動マージしようとして失敗したというメッセージが出ています。
ここでprogram02.txtを開いてみましょう。次のようになっています。
これはリモートリポジトリ側とローカルリポジトリ側でどのような違いが発生しているかを示しています。
<<<<<<< HEAD
や
>>>>>>> 5c646b6a1972af939e85d7273b6d0f95a24e5d52
は、どのコミットオブジェクトかを示すものです。
このファイルを見て修正を行なっていきます。ではそのまま、program02.txtを編集しましょう。次のようにします。
表示するための機能A 表示するための機能B 表示するための機能C
これで機能A~Cがすべて入りました。AさんBさん両者の作業が報われたことになります。これで競合は解決です。
では、新しくなったprogram02.txtをコミットし、リモートリポジトリへのPushまで一気に行きましょう。
C:\work01\hello_repo>git add . C:\work01\hello_repo>git commit -m "競合解決。機能Cを追加" [master 70dd216] 競合解決。機能Cを追加 C:\work01\hello_repo>git push origin master Enumerating objects: 10, done. Counting objects: 100% (10/10), done. Delta compression using up to 4 threads Compressing objects: 100% (6/6), done. Writing objects: 100% (6/6), 742 bytes | 742.00 KiB/s, done. Total 6 (delta 1), reused 0 (delta 0) remote: Resolving deltas: 100% (1/1), done. To https://github.com/MichiharuT/hello_repo.git 5c646b6..70dd216 master -> master C:\work01\hello_repo>
今度は無事、リモートリポジトリへのPushが成功しました。
Pullについて
ちなみにPullは競合の解決時に使うものではありません。ローカルリポジトリの内容を、最新の状態(リモートリポジトリと同じ状態)にするために使うコマンドです。
大規模なシステム開発では、多くの人が絶えずリモートリポジトリを更新している可能性があります。そのため、定期的に自身のローカルリポジトリにもその変更を反映させてあげる必要があります。そのために用いられるのがgit pull
コマンドです。
おわりに
本日はここまでとさせていただきます。最後までご覧くださり、ありがとうございました。競合の解決は実際のシステム開発ではかなり大変な作業です。簡単な例で練習してその感覚をつかんでおくといいと思います。また次回もよろしくお願いします。
合同会社イー・シー・エフでは、子ども向けプログラミングなどの教育講座を実施しています。プログラミング教室の案内や教育教材の情報、また関連するご相談・問い合わせにつきましては下記よりご確認ください。