競合の解決~  365日の紙PHP(15日目)

近代的なPHP開発を行うために

おススメ!記事
Raspberry Pi 用「HAL」で、
カップラーメン・タイマーを作ってみよう!
ラズパイDIYの決定版! ソケットサーバー「HAL」をご紹介します。

競合の解決

さて、バージョン管理の締めくくりとして、今日は競合が起きた場合の解決方法を学びましょう。

競合は、複数人で同じプロジェクトを開発している時などに同じファイルを複数人が編集を行ってコミットしようとする際、全く同じ場所を複数人が修正していた、といった場合に起こります。

Git というバージョン管理システムはとても優秀で、大抵の場合、複数人のコミットは自動でマージ(日本語では「合流」と呼んでいるようです)が行われるのですが、流石に、全く同じ箇所の別の編集は Git にも判断がつきかねますので、人間の目と脳によるマージを行うよう、Git から警告される、ということです。

さて、では競合と解決について、実際にやってみましょう。

1. プロジェクトを2つクローンする

まず、テストのためのプロジェクトを開くため、NetBeans を立ち上げて下さい。もし、Git で既に管理されているプロジェクトしかない場合クローンがしづらいため、プロジェクトを右クリックして「閉じる」を選んで一時的に閉じておきます。(再び開きたくなったら ファイル > プロジェクトを開く で再開できます)

NetBeans画面

そうしたら画面上のメニューから チーム > Git > クローン で bitbucket のリモート・リポジトリ情報が表示されるので、「次 >」を選びます。

リモート・リポジトリ

次は分岐の選択です。まだブランチが作られていない場合は master のみが表示されるでしょう。やはり「次 >」を選びます。

リモート分岐画面

最後にクローンを行う場所と名前です。ここでクローン名を「firstlogin1」等のように別の名前でクローンして下さい。

クローン名の指定

「終了」をクリックするとプロジェクトがクローンされ、プロジェクトを開くかどうかの確認ダイアログが出ますので、「プロジェクトを開く」を選んで開いて下さい。

クローン完了

そうしたら、もう一度同じ作業(クローン)を行い、最後のクローン名の指定で「firstlogin2」のように別の名前でクローンをします。こうなります。

プロジェクト

ファイルブラウザでの確認

※下の画面、OS のファイルブラウザでの firstLogin は昨日までで作っていた元のプロジェクトです。

このようにクローン名を変えて、同じプロジェクトを2つ開きました。これから、わざと競合を起こしてみようと思います。

2. 上のプロジェクトを編集する。

まず、上のプロジェクト(firstLogin1)の login.php を開きます。私のプロジェクトではこんなコードになっています。

コード

そうしたら、どこか適当なところを選んで修正します。私は以下のようにしてみました。

if(!isset($_SESSION["logged"])){
http_response_code(404);
header("Location: index.php");
}

      ↓

if(!isset($_SESSION["logged"])){
http_response_code(500);
header("Location: error.php");
}

これをローカルリポジトリにコミットしてからプッシュします。プロジェクトタブで login.php を右クリックして Git > コミット を実行してから再び右クリックで、Git > リモート > アップストリームへプッシュ です。

(なお、プッシュ というメニューも有りますが、こちらは一番最初にリモートリポジトリにプッシュする場合を除いては使わないほうが良いでしょう。参考)「引数なしのgit pushは危険なので気をつけましょう 」ということのようです)

これで、firstLogin1 の修正がリモートリポジトリにプッシュされました。

3. 下のプロジェクトで同じ場所を編集する。

今度は下のプロジェクトです。元のコードは firstLogin1 と同じなので、全く同じコードが開かれるはずです。私は以下のように修正を行いました。

if(!isset($_SESSION["logged"])){
http_response_code(404);
header("Location: index.php");
}

      ↓

if(!isset($_SESSION["logged"])){
header("Location: login.php");
exit;
}

さて、この login.php を右クリックしてローカルリポジトリにコミットします。

そうしたら次は、アップストリームへプッシュです。すると、こんなダイアログが表示されました。

プッシュ失敗

同じ場所に別々の編集を行ったので、Git がどうあるべきなのか判断がつかないと報告してくれているのです。

そこで、「変更のプル」を選びます。次のような画面が出るので、手動でマージを行うため、「マージ」を選択します。

ダイアログ1

次のようなダイアログが更に表示されるので、「解決」を選びます。

ダイアログ2

すると、マージ競合リゾルバが開きます。

マージ競合リゾルバ

プロジェクトタブの login.php や、開いているlogin.php のタブを見て下さい。ファイル名が赤色で表示されていますね? これが、競合が起きている証です。

さて、では手動でマージ(合流)しましょう。マージ競合リゾルバで受け入れ方を選択します。今回は、「両方を受け入れ」を選んでみました。その画面がこれです。

受け入れ後

if(!isset($_SESSION["logged"])){
header("Location: login.php");
exit;
http_response_code(500);
header("Location: error.php");
}

両方のコードが取り込まれたのでこの辺りが変ですね。適切に修正しましょう。マージ競合リゾルバの画面下の「OK」ボタンでリゾルバを抜けます。login.php の文字が青色に変わっているはずです。あとはこんな感じで正しく修正を行います。

if(!isset($_SESSION["logged"])){
http_response_code(500);
header("Location: error.php");
exit;
}

そうしたらローカルリポジトリにコミットを行い、再びアップストリームへプッシュを行ってみましょう。

こんどは競合が起きずに正常にプッシュが行えたはずです。

プッシュ完了

4. Git でプッシュする場合の作法

ところで、今回はプッシュを行った後に警告がでましたが、本来はプッシュを行う前に競合が起きないように解決しておくことが推奨されます。

どうするのでしょうか?

まず、上のプロジェクトの login.php を開いて下さい。下のプロジェクトの login.phpをプッシュしたので、内容が一致していませんね。

この状態で、上のプロジェクトの login.php の該当箇所をまた書き換えてみます。

if(!isset($_SESSION["logged"])){
echo "テストだよ";
}

この状態でローカルリポジトリにコミットします。

そうしたら、いきなりアップストリームへプッシュするのではなく、まず「プル」します。login.php を右クリックして Git > リモート > アップストリームからプル です。

すると、先ほどのようなダイアログが出ます。

プルでのダイアログ

ここでマージを選ぶと、やはり、先ほどと同じダイアログが出るので手動解決します。やり方は全く一緒です。

手動解決

解決を行ってファイル名が青色になったらコミットを行い、晴れてリモートリポジトリのアップストリームにプッシュしましょう。

このように、ローカルで競合を解決してからプッシュを行うのが正しい Git での作法なのです。

ですからつまるところ、コードを修正する際には何よりも先にまず「アップストリームからプル」してリモートリポジトリのコードを取得し、それからコードの編集を始めるのが最も効率が良い方法です。

まとめ

今回までで、4 回にわたって NetBeans での Git の利用について説明してきましたが、大体ご理解いただけたでしょうか?

バージョン管理システムは、現在の IT の開発現場では無くてはならない物になりつつあります。

何時、どんな修正を加えたのかを記すだけでなく、いつでもどの状態にでも戻すことができ、チーム開発を円滑に進める事もできる Git は本当に有益なアプリケーションです。

怖がらずに是非 Git を導入し、効率的な開発を行っていってください。

明日からは、いよいよ、データベースを取り扱ってみようと思います。

この記事へのコメント

※現在コメントはMarkdown記法が強制です。>>Markdown の書き方


この記事に返信

このコメントに返信