tanaka's Programming Memo

プログラミングについてのメモ。

GitHubでみんなで開発2016年度版-管理者編

オリジナルリポジトリーを管理できるように、プルリクエストの対応方法をまとめます。

前提

準備

すでにプルリクエストされるリポジトリーがあれば、プルリクエストをダウンロードするへ進んでください。練習をしたい人は、二人以上のグループで、以下の作業をしてください。

Webブラウザーhttps://github.com を開いて、ログインしてから作業を開始しましょう。

リポジトリーを作成する

Unity の新規プロジェクトを作成して、プルリクエストを送りあってみましょう。

  • Unity を起動して、New で AdminRensyu などの名前でプロジェクトを作成

バージョン管理をしやすくするための設定をします。[Inspector]ビューで、以下を設定してください。

  • [Edit]メニューから[Project Settings]>[Editor]を選択
  • [Version Control]欄を[Visible Meta Files]に変更
  • [Asset Serialization]を[Force Text]に変更 f:id:am1tanaka:20170204234425p:plain

保存します。

  • [File]メニューから[Save Scene]を選択して、[Test]などのシーン名で保存
  • [File]メニューから[Save Project]を選択

以上で、雛形の状態ができました。これを GitHub Desktop に登録します。

GitHubへの登録

  • [Project]ビューの[Test]スクリプトを右クリックして、[Show in Explorer]を選択して、プロジェクトの場所をエクスプローラーで開く
  • Assets フォルダーが開くので、一つ上のフォルダーへ移動 f:id:am1tanaka:20170204234520p:plain
  • そのフォルダーのパスをコピーしておく
  • GitHub Desktop を起動
  • 左上の[+] > [Add] をクリック
  • [Local path]欄に、先ほどコピーした Unity のプロジェクトフォルダーのパスを貼り付ける f:id:am1tanaka:20170204234536p:plain
  • 下に!が表示されて、[create a repository]がクリックできるので、クリック(!のメッセージが表示されない場合は、Unityのプロジェクトを、Unity Projects フォルダーか、GitHub フォルダー内に移動してから、再度試してみてください)
  • [Create]に切り替わるので、[Git ignore]を[Unity]にして、[Create repository]をクリック f:id:am1tanaka:20170204234551p:plain
  • [Changes]をクリック
  • [Summary]欄に「プロジェクトを追加」などと入力して、[Commit to master]をクリック
  • Publishを押す
  • Description欄に「GitHubの管理者練習用リポジトリー。」などのように入力
  • [Publish <リポジトリー名>]をクリック

以上で、練習用のリポジトリーの作成が完了した。

練習用リポジトリーのフォークとクローン

作成した練習用リポジトリーの URL を、練習相手と教えあいましょう。自分が作成した練習用リポジトリーの URL の確認方法は以下の通りです。

練習相手のリポジトリーの URL を Webブラウザーのアドレスバーに入力して開きます。

GitHubでみんなで開発2016年度版 - tanaka's Programming Memo の手順に従って、練習相手のリポジトリーをフォークして、 GitHub Desktop でクローンをしてください。

Unity で変更を加える

クローンしたリポジトリーは、 AdminRensyu-1 のような名前になっていると思います。それを、 Unity で開いてください。

  • Unity に切り替える
  • [File]メニュー > [Open Project…] を選択
  • クローンしたリポジトリーのフォルダーを選択して開く

Unityが起動したら、以下の変更を加えましょう。

  • [Hierarchy]ビューの[Create]をクリックして、[3D Object]>[Cube]で立方体を作成する
  • 作成した[Cube]を選択して、[Inspector]ビューの[Add Component]をクリックして、[New Script]を選択
  • 名前を[Test]などにして、[Create and Add]を選択して、スクリプトを作成して、Cubeにアタッチする
  • [File]>[Save Scenes]でシーンを保存
  • [File]>[Save Project]>でプロジェクトを保存

以上で、プルリクエストする内容ができました。

プルリクエストの作成

プルリクエストを作成します。プルリクエストをする前に、コミットしておく必要があります。

  • GitHub Desktop に切り替える
  • [Changes]をクリック
  • [Summary]欄に「Cubeの追加」などと入力して、[Commit]

プルリクエストを実行します。

  • GitHub Desktop の[Pull request]をクリック f:id:am1tanaka:20170202234904p:plain
  • [from master into ・・・]の部分が[master]としか表示されていなかったら、[master]をクリックして、[Other branches]の下に表示されているリポジトリーを選択する
  • Title 欄と Description 欄に、相手に伝えたいコメントがあれば入力する。特になければそのままでよい
  • [Send pull request]をクリック

以上で、プルリクエストを発行することができました。Webブラウザーで自分の練習用リポジトリーを開いて、プルリクエストが届くのを待ってください。

プルリクエストをダウンロードする

自分が管理している GitHub リポジトリーにプルリクエストが届いたら、プルリクエストされたリポジトリーを手元のPCにダウンロードして、動作確認をしましょう。

  • WebブラウザーGitHub を開いてログイン
  • 管理しているリポジトリーを開く
  • プルリクエスト(Pull Requests)タブをクリック f:id:am1tanaka:20170204233414p:plain
  • リストが表示されるので、確かめたいプルリクエストを選択
  • [open this in GitHub Desktop]のリンクをクリック f:id:am1tanaka:20170204233437p:plain

クリックしてから、実際に実行されるまでしばらく時間がかかる場合があります。反応がなくても、1分程度は待ってください。

GitHub Desktop が起動して、ブランチが[pr/23]のように表示されれば成功です。プルリクエストされたプロジェクトを確認できます。

プルリクエストされた状態を確認

プルリクエストされた状態の動作を確認します。

  • 画面左のリポジトリーを右クリック
  • [Open in Explorer]を選択して、クローンしたフォルダーを確認
  • Unityを起動
  • [Open]を選択して、クローンしたフォルダーを選択して開く

プロジェクトが開いたら、実行して、動作を確認します。

変更されたファイルを確認する

何が変更されたかは把握しておく必要があります。GitHub Desktop で簡単に確認ができます。

  • [History]をクリック
  • コミットのリストが表示されるので、確認したいコミットをクリック
  • 画面右に、変更があったファイルの一覧が表示される
  • [+]をクリックすると、中身が確認できる。問題点がないかを確認する f:id:am1tanaka:20170204233634p:plain

問題点を報告

動作確認や、変更されたファイルをチェックして、不具合があったり、コードがよくなかったりした場合、修正して欲しい箇所をプルリクエストした人に知らせて修正をお願いします。

  • Webブラウザーでプルリクエストのタブを開く
  • マージ欄の下の [Leave a comment] 欄に、伝えたいコメントを書いて、[Comment]ボタンを押す f:id:am1tanaka:20170204233733p:plain

これを、受け入れができる状態になるまで繰り返します。

変更を受け入れる

プルリクエストの内容に問題がなくなったら、最新の master ブランチに結合(マージ)します。

マージする時にファイルに変更があってはいけません。自分で修正したことがあればコミットをします。

変更を取り消す操作

変更した覚えがないのに、変更があったら以下の操作で変更を取り消すことができます。

  • GitHub Desktop の[Changes]を選択 > 取り消したい変更を右クリック > [Discard changes]を選択 f:id:am1tanaka:20170204234049p:plain

以上で、前回コミットした状態に戻すことができます。

マージ

変更点がなくなったら、 master ブランチに、プルリクエストの内容を取り込みます。手順が逆にならないように注意してください。

  • GitHub Desktop のブランチをクリックして、[pr/??]ブランチを[master]に切り替える f:id:am1tanaka:20170204233857p:plain
  • [Compare]をクリックして、[pr/??]に切り替える
  • [Update from pr/??]をクリック

以上で完了です。ブランチの方向を間違えたり、失敗したら、一度クローンしたフォルダーを削除して、プルリクエストの内容をクローンするところからやり直すと楽です。

GitHubへ反映させる

何も起きなければ、GitHub Desktop で [Publish]、或いは[Sync]を押して、 GitHub へ反映させれば完了です。

Issues を閉じる

Pull Request が Issues で報告されている内容を解決するものであったら、その Issues を閉じましょう。

  • GitHub Desktop の左からリポジトリーを右クリックして、 [View on GitHub]を選択して、WebブラウザーGitHub を開く
  • [Issues]をクリック
  • 一覧表示の中から、処理した Issues をクリック
  • コメントがあれば [Leave a comment] 欄に入力する。なければ空欄でよい
  • [Close issue]を押す f:id:am1tanaka:20170204234149p:plain

以上で、Issue がクロースされて、リストから非表示になります。[Issues]タブをクリックして、Issue リストを表示すると、閉じた項目は表示されなくなります。 [Closed]をクリックすると、閉じた Issue を見ることができます。


コンフリクトさえ発生しなければ、ここまで OK です。ここからは、コンフリクトが発生した時に備えての演習を紹介します。

コンフリクト解決の練習

master ブランチに何事もなくマージできればよいのですが、同時に同じ場所を編集した場合、コンフリクト(Conflict=衝突)が発生します。これの解決が、共同開発する時の最大の難題です。コンフリクトが発生した時の対応方法を練習しましょう。プルリクエストの練習で利用したリポジトリーで引き続き作業をしましょう。

プロジェクトを開く

  • Unity に切り替える
  • [File]メニューから、[Open Project]を選択
  • 自分が作成した AdminRensyu プロジェクトフォルダーを選択して開く

コンフリクトを仕込む

コンフリクトは、同じ場所に変更を加えることで発生します。ブランチを2つ作成して、それぞれで Test スクリプトの同じ場所に違う変更を加えることでコンフリクトさせましょう。

  • GitHub Desktop で [Create new branch] を押す
  • [conflict1]などの名前を入力して、[Create new branch]で新しいブランチを作成
  • ブランチを[master]に戻す
  • 同様に、[conflict2]というブランチを作成
conflict2の作業

まずは、conflict2 ブランチに変更を加えます。以下、Unityで作業します。

  • [Cube]の X 座標を -1 にする
  • [Project]ビューの[Test]スクリプトをダブルクリックして、エディターで開く
  • 以下のコードにする
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {

    // Update is called once per frame
    void Update () {
        Vector3 next = transform.position;
        next.x+=1f*Time.deltaTime;
        transform.position = next;
    }
}
  • 上書き保存して、Unityに切り替える
  • [File]メニューから[Save Scene]を選択
  • [File]メニューから[Save Project]を選択

実行すると、キューブが右に移動します。これをコミットします。

  • GitHub Desktop に切り替える
  • [Summary]欄に、「座標の変更と右へ移動」と入力
  • [Commit to conflict2]をクリック
conflict1の作業

コミットが完了したら、conflict1 に切り替えて、同じ場所に別の変更を加えます。

  • GitHub Desktop で、ブランチを[conflict1]に切り替える
  • Unityに切り替える
  • リロードの確認ウィンドウが表示されるので、[Reload]を押す
  • [Project]ビューから[Test]シーンをダブルクリック

これで、master からブランチを作成した時点に戻ります。別の変更を加えます。

  • [Hierarchy]ビューから[Cube]を選択
  • X座標を 1 に変更
  • [Project]ビューの[Test]スクリプトをダブルクリックする
  • 起動したら、スクリプトを以下のようにする
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {

    // Update is called once per frame
    void Update () {
        Quaternion now = transform.rotation;
        Quaternion rot = Quaternion.AngleAxis(90f*Time.deltaTime, Vector3.up);
        rot = rot*now;
        transform.rotation = rot;
    }
}
  • 上書き保存して、Unityに切り替える
  • [File]メニューから[Save Scene]を選択
  • [File]メニューから[Save Project]を選択

実行すると、キューブが回転します。これをコミットします。

  • GitHub Desktop に切り替える
  • [Summary]欄に、「座標の変更と回転」と入力
  • [Commit to conflict1]をクリック

コンフリクトを発生させる

conflict1 ブランチと conflict2 ブランチを master ブランチにマージして、コンフリクトを発生させます。

  • GitHub Desktop に切り替え
  • [master] ブランチに切り替える
  • [Unity]に切り替えて、ビルドされるのを待ち、ウィンドウが表示されたら[Reload]ボタンを押す
  • GitHub Desktop に戻る
  • [Compare]をクリックして、[conflict1]を選択
  • [Update from comflict1]ボタンを押す
  • [Unity]に切り替えて、ビルドされるのを待ち、ウィンドウが表示されたら[Reload]ボタンを押す

これで、 master ブランチに conflict1 ブランチがマージされます。master は conflict1 を実装開始する時から変更されていないので、コンフリクトは起きません。実行すると conflict1 の内容である Cube の回転が見られます。

次に、 conflict2 ブランチをマージします。

  • GitHub Desktop に切り替える
  • [conflict1]をクリックして、[conflict2]に切り替える f:id:am1tanaka:20170204234752p:plain
  • [Update from conflict2]をクリック
ここでコンフリクトが発生します(Unable to merge=マージできません)!

[View conflicts]を選択して、コンフリクトを表示します。 f:id:am1tanaka:20170204234822p:plain

コンフリクトが発生した一覧が表示されて、右に[!]マークが表示されます。今回は2つのファイルが該当します。これを全て解決します。 f:id:am1tanaka:20170204234833p:plain

コンフリクトを解決する

衝突している部分は、「<<<<<<< HEAD」「=======」「>>>>>>> <ブランチ名>」の3つの記号の行で示されます。

  • 「<<<<<<< HEAD」から「=======」の間は、現在のコード
  • 「=======」から「>>>>>>> <ブランチ名>」の間は、マージしようとしているコード

いずれか一方を残すか、あるいは両方残して、3つの記号の行を削除することで、コンフリクトを解決することができます。まずは、Test.csから解決します。

Test.csを解決

Test.cs には、移動と回転のコードが追加されています。これは、両方とも採用することにします。その場合は、区切りの記号行を削除するだけで解決します。

  • Unity の [Project]ビューで[Test]スクリプトをダブルクリックして、エディターで開く
  • 記号の行を3つとも削除して、以下のようにする
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {

    // Update is called once per frame
    void Update () {
        Quaternion now = transform.rotation;
        Quaternion rot = Quaternion.AngleAxis(90f*Time.deltaTime, Vector3.up);
        rot = rot*now;
        transform.rotation = rot;

        Vector3 next = transform.position;
        next.x+=1f*Time.deltaTime;
        transform.position = next;
    }
}
  • 上書き保存する

以上で、 Test.cs の衝突は解決しました。まだ、衝突が残っているので、 Unity に切り替えてもエラーになります。衝突は、全て解決する必要があります。

Test.unityを解決

Unityでバージョン管理をする時の最大の困難は、[.unity]ファイルのような Unity の設定ファイルが衝突した時です。今回は、 Cube オブジェクトの座標に関する設定がコンフリクトしました。プレハブなどでも同じように発生します。

設定ファイルの場合、項目ごとに1つのパラメータになるはずなので、 Test.cs でやったように両方残すことは有り得ません。衝突した変更をした担当者に何を変更したかを聞き取り、どちらか一方の変更を採用するようにします。

今回は、 conflict2 の方を採用することにします。

  • [Unity]に切り替える
  • リロードのダイアログが表示されたら、[Reload]をクリック
  • [Project]ビューから[Test.cs]などを右クリックして、[Show in Explorer]でプロジェクトフォルダーを開く
  • 該当ファイル(ここでは Test.unity )を右クリックして、Atom などのテキストエディターで開く
  • GitHub Desktop で Test.unity を選択すると、変更箇所が表示されるので、行番号を確認する
  • 変更点を、以下のように修正する
    • 変更前
<<<<<<< HEAD
  m_LocalPosition: {x: 1, y: 0, z: 0}
=======
  m_LocalPosition: {x: -1, y: 0, z: 0}
>>>>>>> refs/heads/conflict2
  • 変更後
  m_LocalPosition: {x: -1, y: 0, z: 0}
  • 上書き保存して、 Unity に切り替える
  • ダイアログが表示されたら[Reload]をクリック

以上で全ての衝突が解決しました。 Unity が実行できるようになるので実行してください。座標はやや左から(conflict2の座標)、回転しながら右に移動します。

解決した内容をコミットする

衝突を解決したら、コミットします。

  • Unityで[File]から[Save Scene]、[File]から[Save Project]を実行して、保存する
  • GitHub Desktop に切り替える
  • 衝突しているファイルはチェックが外れているので、チェックを入れる f:id:am1tanaka:20170204235127p:plain
  • 必要であれば、 Summary や Description を書き換える。そのままでよければそのままでよい
  • [Commit to master]をクリック

以上で解決です。

まとめ

簡単なプルリクエストへの最小限の対処方法をまとめました。コンフリクトが発生すると、面倒になることが確認できたと思います。適切にファイルを分割して、作業担当を割り振れば、コンフリクトは減らすことができます。色々と試してみてください。

コンフリクトが発生したら、衝突場所を示す記号の行がテキストファイルに挿入されます。そのままではプログラムは動かなくなるので、残したいコードを残し、不要なコードを削除しながら、記号の行を削除します。

コンフリクトで厄介なのは、 Unity が管理している設定ファイルが衝突した時でした。その場合は、どちらか一方を採用することにして、一方の変更を削除するようにするとよいでしょう。

ここで紹介したことに加えて、書式をチェックする Linter ツールや、自動的テストを導入すると、さらに開発がしやすくなります。手順が飲み込めたら、そのような自動化ツールも調べてみましょう。

色々とややこしいですし、ここに書いてあるのはごく初歩的な部分だけです。実際にやってみると、様々なことが発生することでしょう。それらを沢山体験しておくと、今後に活きてきます。早速、自分たちでプロジェクトを立ち上げて、共同開発に挑戦してみてください。

参考URL