はじめに

INTER-Mediatorへのソースコードを投稿する場合の手順をまとめておきます。INTER-Mediatorのコミッターや、あるいはバグレポートの1つの方法として、ソースコードの投稿を歓迎します。手順は、Webサイトを利用した、いちばん手軽な方法が中心です。

ソースコード投稿の考え方

INTER-Mediatorはオープンソースプロジェクトであり、コミュニティを形成することで、開発が進行する手法を取り入れています。多くの方々によってソースコードがレビューされることで、システム全体が洗練され、セキュリティ的な問題点が解消されることが期待できます。また、新たな機能やバグ修正等のソースコードの投稿を受け付けることで、システムの継続的な進化も期待できます。そのために、INTER-Mediatorでは、GitHubを利用した「Pull Request」によるソースコードの投稿を広く受け付けることとします。

GitHubの組織「INTER-Mediator」

INTER-Mediatorは、GitHub上に「INTER-Mediator」という名称の組織を作成しており、そこにあるレポジトリが「マスターレポジトリ」となります。コミッターの開発結果はこのマスターレポジトリにまとめられますが、まとめる作業は、INTER-Mediator Directive Committeeのメンバーによって行われます。レポジトリの1つ「INTER-Mediator」は、フレームワーク本体やサンプルプログラムなどのソフトウエア全般がまとめられています。「INTER-Mediator_WebSite」は、INTER-MediatorのWebサイトのソースです。「INTER-Mediator」はForkをしてPull Requestを送る手法を基本とします。「INTER-Mediator_WebSite」はINTER-Mediator Directive Committeeメンバによる書き込み権限を与えることで、Forkをしないで単一のレポジトリでの運用を基本とします。したがって、本文書に書かれた内容は、フレームワーク本体の「INTER-Mediator/INTER-Mediator」というレポジトリの運用方法を記載したものとなります。

GitHubアプリケーションを使ったPull Request

GitHubはバージョン管理システムのgitをベースにしており、すべてはgitのコマンドでできると言えますが、コマンドでの処理は習得に時間がかかると同時に失敗しやすいということもあります。しかしながら、GitHubは専用アプリケーションをリリースしており、そのアプリケーションを利用することで、ソースコードの投稿を簡単にできるようになっています。ここでは、なるべくGitHubアプリケーションと、GitHubのサイトを利用するということで、ソースコードを取得し、修正後に投稿する流れを説明します。

組織で管理しているマスターレポジトリは「INTER-Mediator/INTER-Mediator」と記載します。Gitの表記にしたがって「組織名/レポジトリ名」でレポジトリを記述することにします。ここで、GitHubのあるユーザmsykが、INTER-Mediator本体のレポジトリに対して、ソースコードの追加等を行い、その開発結果を投稿しようとします。

ソースコードの取得を最初に行いますが、その作業を「マスターレポジトリをForkする」などと呼ばれます。Forkにより、レポジトリの複製を自分自身のアカウントの領域に作成をします。マスターレポジトリへの書き込み権限を持つ人は限られていますが、パブリックなプロジェクトなので、逆にソースコードは誰でも取得できます。したがって、GitHubにアカウントがあれば、誰でもForkができることになります。GitHubにユーザmsykでログインをして作成した、ユーザmsykのINTER-Mediatorフレームワーク本体は、「msyk/INTER-Mediator」と記述をします。さらに、現実には、自分のアカウントにあるリモートのレポジトリのクローンを作業者のMac/PCの中にローカルのレポジトリとして作成をします。ソースコードの改変をする前に、まず、ここまでの準備が必要です。概念図は以下のとおりで、左側のマスターレポジトリをForkして、あるユーザのリモートレポジトリを作成し、そのクローンのレポジトリがローカルにあるという状態です。ここで、masterはブランチ名で、「A」はある状態を示します。この後に、ローカルのレポジトリのソースコードを変更した結果、状態が「B」になるというような図が出てきます。

Forkする

Forkをするには、GitHubに自分のアカウント(この場合はmsyk)でログインをします。そして、組織のページに移動して、マスタレポジトリのトップページを表示します。組織のマスターレポジトリは、レポジトリ名が「INTER-Mediator/INTER-Mediator」となっていることから、判別できます。そして、右上にある「Fork」のボタンをクリックします。これだけで、自分の領域にマスターレポジトリの複製のレポジトリが作成されます。なお、単に複製するだけでなく、マスターレポジトリが元々のオリジナルであることもきちんと記録されています。

「Fork」ボタンをクリックした後、画面が遷移して、自分自身の複製したレポジトリのページに移動しています。レポジトリ名が「msyk/INTER-Mediator」となっていて、ユーザmsykにINTER-Mediatorというレポジトリが作られたことがわかります。この段階では、マスターと同一のレポジトリです。

ローカルにクローンを作成する

さらに自分のレポジトリのクローンを自分のMac/PCに作成します。ここで、クローンはコマンドラインで作る方法などいろいろありますが、使用しているパソコンにGitHubアプリケーションをインストールしておけば、レポジトリのページの「Clone in Desktop」のボタンをクリックし、そしてローカルレポジトリを作るフォルダを指定するだけで、作成することができます。

コマンドラインで作るときには、ローカルレポジトリを作りたいフォルダをカレントフォルダにして、「git clone [レポジトリのURL]」と入力します。レポジトリのURLは、やはりレポジトリのページ右側にある「HTTPS clone URL」の部分のURLを指定しますが、コピーボタンがあるので、URLをコピーし、コマンドライン入力中にペースとすれば良いでしょう。

変更結果をPull Requestする

自分のローカルのレポジトリ内で、ファイルを修正したとします。その修正処理はmasterでもいいですが、独自に作成したブランチでもかまいません。以下の図では、「readme-file-modify」というローカルのブランチに、変更結果が存在する状態です。そして、GitHubアプリケーションで、ツールバーの右から2つ目のボタンをクリックすることで、Pull Requestを作成します。パネルをクリックすると、右側に「Pull Request」の薄青い背景のパネルが表示されます。ここで、最初のテキストボックスに概要、そして、広いテキストフィールドにはある程度の説明を入力します。

タイトルの直下の部分で、マージを希望する先のマスターレポジトリのブランチを指定してください。右側はローカルで現在選択されているブランチができていて、ここは変更できません。右側はクリックするとドロップダウンリストが表示され、レポジトリを選択できます。ローカルと同じ名前のブランチの場合で、マスターリポジトリにブランチがない場合、そのブランチはマスターレポジトリに作られます。「Send Pull Request」ボタンをクリックします。このPull Requestは、Forkしたレポジトリの元のレポジトリに送り届けられます。

リクエストでは、取り込み先のブランチを選択できます。通常、最終的に変更結果はmasterに統合されるので、完成した機能やあるいはバグの修正となると、masterに統合することでかまいません。一方、機能そのものが一部しか実現していないものの、その結果を他のデベロッパーにも見てもらいたいといった理由があれば、ブランチにPull Requestを送ってください。その後の統合作業については、ディスカッションの上進めましょう。

Pull Requestが終了するとメッセージが表示され、GitHubのサイトへのリンクも見えています。ここでは#220という番号も見えています。GitHubアプリケーションを使えば、Pull Requestはこのように簡単に作成できます。

マスターレポジトリの更新結果の取り込み

Pull Requestによって、複数の開発者からのPull Requestが行われると、当然のこととしてマスターレポジトリはどんどん更新され、それぞれのユーザのレポジトリは以前の状態のままになります。Pull Requestを出したユーザは、自分と同じ状態にマスターレポジトリが更新されたので、同一の状態になっています。しかしながら、別のアカウント(以下の図にあるsomeone)が、msykによるPull Requestを発行する前にForkして、自分アカウントにレジストリーを作っていたとしたら、組織のアカウントは状態Bになっても、someoneの方は状態Aのままになります。someoneのレポジトリは状態Bにしたいと考えます。

一時期はGitHubアプリケーションの右上にある「Sync」ボタンをクリックするだけで、自分のローカルのレポジトリを、Forkした元のマスターレポジトリと同じ状態にできましたが、これは「バグ」だったようで、その後にこの作業は自動的にできなくなっています。Syncは、ローカルとその元になっているレポジトリの間だけの同期です。

Forkした元のレポジトリの更新結果を受け入れるには、以下のようにコマンドラインで作業をします。コマンドは、カレントディレクトリが、ローカルレポジトリのフォルダのルートになっている状態で入力します。最初のgit remote -vを見ると、自分自身のGitHub上のレポジトリに対してorignという名前が付けられ、加えて、Fork元のレポジトリは、「INTER-Mediator」という名前が付けられています。よくある作業例ではupstremという名前付けが一般的ですが、この「INTER-Mediator」は、GitHubアプリケーションが自動的に定義を加えています。そして、fetchでFork元のレポジトリを取り込んで、現在のブランチ(ここでは、ローカルレポジトリのmasterが選択されているとする)に、Fork元のレポジトリのmasterブランチの更新結果をマージします。

$ git remote -v
INTER-Mediator  https://github.com/INTER-Mediator/INTER-Mediator.git (fetch)
INTER-Mediator  https://github.com/INTER-Mediator/INTER-Mediator.git (push)
origin  https://github.com/msyk/INTER-Mediator.git (fetch)
origin  https://github.com/msyk/INTER-Mediator.git (push)
$ git fetch INTER-Mediator
$ git merge INTER-Mediator/master
Updating 757ee4a..e41aabd
Fast-forward
 INTER-Mediator-UnitTest/sha1-test.js |  10 +++++
 LICENSE                              |   4 ++
 dist-docs/License.txt                |  29 ++++++++++++++
 dist-docs/buildup.sh                 |   2 +-
 dist-docs/change_log.txt             |   2 +
 dist-docs/readme.txt                 |   4 +-
 dist-docs/vm-for-trial/index.html    |   8 ++--
 lib/js_lib/sha1.js                   | 185 ----------------------------------------------------------------------------------------
 lib/js_lib/tinySHA1.js               |   1 +
 9 files changed, 53 insertions(+), 192 deletions(-)
 create mode 100644 INTER-Mediator-UnitTest/sha1-test.js
 create mode 100644 LICENSE
 delete mode 100644 lib/js_lib/sha1.js
 create mode 100644 lib/js_lib/tinySHA1.js

GitHubのWebサイトからPull Requestを送る

ここまでにGitHubアプリケーションを使用した方法で、投稿から更新結果の受け取りまでを説明しました。ここからは、これらの作業をGitHubアプリケーションを使わないで行う方法を説明します。

変更結果を自分のレポジトリにpush

Pull RequestをGitHubアプリケーションを使わないで行うには、まず、変更結果を、自分のレポジトリに反映させます。

ローカルのレポジトリであらたなブランチを作ったり、あるいはマスターレポジトリにすでにブランチがある場合には、そのブランチを現在利用するブランチとしてプログラムの追加や変更を行います。ブランチの切り替えは、GitHubアプリケーションのツールバーでBranchesのボタンをクリックし、ブランチの一覧にある右端の▼をクリックして、「Switch to This Branch」を選択します。プログラムの変更を行った後は、GitHubアプリケーションのツールバーでChangesを選択し、CommitとSyncを行います。Syncにより現在のブランチへのpushも行います。

ローカルのレポジトリではmasterブランチのまま作業をして、それを自分のリモートレポジトリにpushするときに、新たなブランチを作成するの良いでしょう。たとえば、PHPStormで作業をしているのであれば、ブランチに含めたいファイルを選択したり、あるいはルートのフォルダを選択するなどして、VCSメニューからCommit Changesを選択します。するとコミットされるファイルの一覧と、コミットメッセージが見えるダイアログボックスが表示されます。メッセージを書き込んだ上で、Commitボタンにマウスポインタを移動させるとポップアップメニューが出るので「Commit and Push」を選択します。すると、さらにGit Pushと書かれたダイアログボックスが表示されるので、その下の部分のチェックボックスをオンにして、右側のテキストフィールドに、新たなブランチ名をキータイプします。すると、コミット結果が新たなブランチにpushされ、リモートレポジトリにここで入力した名前のブランチが作成されています。

Pull Requestの作成

ここまでの作業で、変更結果は、自分のリモートレポジトリ側には反映されていますが、これをマスターに反映するためには、Pull Requestをマスターレポジトリに対して要求します。以下の図では、new-funcというブランチに、改変結果が記録されているので、そのブランチをマスターレポジトリへ取り込んでもらうということを示しています。

ここまでの作業で改変した結果は自分自身のリモートレポジトリにあります。自分のアカウントでログインをして、自分のリモートレポジトリのページを開きます。ここで、ファイルリストの上の部分に、薄い黄色の枠で、Your recently pushed branches:という記述があれば、そこにある「Compare & pull request」ボタンをクリックします。もし、出ていないようであれば、ファイルリストの上部の「branch: master」などと書かれいる部分からブランチを選択して、その左の緑色のボタンをクリックして、移動したページで「Create Pull Request」ボタンをクリックします。

Pull Requestを作成するページになります。ここで、追加した機能の概要などを記載して「Create pull request」ボタンをクリックします。作業はこれだけです。このユーザ側のレポジトリは、マスターリポジトリからForkしたものなので、このPull Requestは、マスターレポジトリ側に送られます。

Pull Requestの受け入れ

マスターレポジトリ側での受け入れ作業は、INTER-Mediator Directive Committeeで行います。Pull Requestがあれば、それをいったんマスターレポジトリにpullします。その段階では、リクエストを送ったのと同じブランチ名のものがマスターレポジトリにできあがります。そして、動作の検証やコードのレビューを行います。masterではないブランチでPull Requstがあったものは、masterへマージします。この場合、マスターレポジトリでPull Requestを行い、それを受け入れればmasterに反映されるということになります。

受け付けられたPull Requestはマスターレポジトリ側はでは次のように見えます。

マスターレポジトリからの部分的な受け入れ

GitHubアプリケーションを使えばSyncによりマスターレジストリの内容を即座にローカルに取り込むことができます。その作業をコマンドだけで行う方法を、以下に記述します。ローカルレポジトリをマスターとは異なる状態で保持する必要がある場合などには、この方法を応用して、必要な更新だけを取り込むようにします。以下、青色で太字が入力するコマンドで、#で始まるグレーの文字は説明です。

# Forkした自分のレポジトリをローカル側にクローンを作る(すでに作成済みなら不要)
$ git clone https://github.com/msayukinii/INTER-Mediator.git
Cloning into 'INTER-Mediator'...
remote: Counting objects: 7408, done.
remote: Compressing objects: 100% (2387/2387), done.
remote: Total 7408 (delta 4983), reused 7408 (delta 4983)
Receiving objects: 100% (7408/7408), 8.04 MiB | 1.71 MiB/s, done.
Resolving deltas: 100% (4983/4983), done.
Checking connectivity... done.
# ローカルレポジトリのルートをカレントディレクトリにする
$ cd INTER-Mediator/
# 現在、masterブランチが選択されている。自分のレポジトリにはmaster以外に
# targeting-generalizationというブランチもあり、ローカル側にもそのブランチはある
$ git branch -a * master targeting-generalization remotes/origin/HEAD -> origin/master remotes/origin/master remotes/origin/targeting-generalization # リモートレポジトリの一覧を見る。自分のリモートレポジトリが見えている $ git remote -v origin https://github.com/msayukinii/INTER-Mediator.git (fetch) origin https://github.com/msayukinii/INTER-Mediator.git (push) # 新たに、マスターリポジトリをupstreamという名前でローカルリポジトリに登録する $ git remote add upstream https://github.com/INTER-Mediator/INTER-Mediator.git # originだけでなくupstreamも管理対象のリモートレポジトリとして登録された $ git remote -v origin https://github.com/msayukinii/INTER-Mediator.git (fetch) origin https://github.com/msayukinii/INTER-Mediator.git (push) upstream https://github.com/INTER-Mediator/INTER-Mediator.git (fetch) upstream https://github.com/INTER-Mediator/INTER-Mediator.git (push) # upstreamで指定されるレポジトリの内容を取り込む $ git fetch upstream remote: Counting objects: 13, done. remote: Compressing objects: 100% (10/10), done. remote: Total 13 (delta 4), reused 7 (delta 3) Unpacking objects: 100% (13/13), done. From https://github.com/INTER-Mediator/INTER-Mediator * [new branch] master -> upstream/master * [new branch] targeting-generalization -> upstream/targeting-generalization # remotes/upstreamの2つのブランチが新たに加わった $ git branch -a * master targeting-generalization remotes/origin/HEAD -> origin/master remotes/origin/master remotes/origin/targeting-generalization remotes/upstream/master remotes/upstream/targeting-generalization # upstream/masterを現在のローカルのmasterにマージする。これで、ローカルのmasterは、マスターレポジトリのmasterと同一の内容になった $ git merge upstream/master Updating 10e5c96..720ff24 Fast-forward DB_Null.php | 177 +++++++++++++++ INTER-Mediator-Element.js | 27 --------------- README.md | 2 +- Samples/templates/definition_file_full.php | 1 + 4 files changed, 179 insertions(+), 28 deletions(-) create mode 100644 DB_Null.php # 自分のリモートレポジトリのmasterに、ローカルの内容をpushすることで、リモート側にも反映される。ただし、この作業は必須ではない $ git push origin master # さらにマスターレポジトリ側の別のブランチを取り込みたいのなら、まず、ローカル側を受け入れるブランチに切り替える $ git checkout targeting-generalization Switched to branch 'targeting-generalization' Your branch is ahead of 'origin/targeting-generalization' by 2 commits. (use "git push" to publish your local commits) # すでにマスターレポジトリのブランチは取り込んであるので、マージすれば、このブランチもマスターレポジトリの内容と同じになる $ git merge upstream/targeting-generalization Already up-to-date! Merge made by the 'recursive' strategy.

上位の一連のコマンドの流れを図示すると次のようになります。一度、upstreamで参照を作っておけば、以後は、fetchしてmergeすることで、マスターレポジトリの内容をローカルのmasterに取り込むことができます。

最初に前提として「masterが正」であるということを記述しましたが、場合によっては、機能が完成する前にレビューや共同作業目的で、ブランチのPull Requestが発生するかど思われます。そういうブランチはマスターレポジトリに残したままになり、fetchによってupstreamにも取り込まれます。こちらは必要に応じてマージすればいいと思われます。また、共同で新たな機能を作る場合、各自がForkしたレポジトリで作業するのは、更新結果の配布に時間がかかることも予想されます。その場合、共同開発している中の1人のForkしたレポジトリに他の開発者も書き込み権限を与えて登録して、単一のレポジトリで各自がcommit/pushするという開発モデルの方が効率がいいと思われます。