Github Desktopを用いたじゃんけんゲーム開発(異常系シナリオ)
Gitを利用して開発をすすめる際,開発者の意図しない状態にリポジトリが陥ることがある.本演習では,代表的な異常状態の対応方法を実際に体験し,学習する.
下記に示す異常系を想定した一連の開発の流れ(E1~E12)について具体的な操作方法を詳述する.各手続きで何を行っているかよく理解したうえで演習を進めること.なお,異常系シナリオは前節の正常系シナリオが終了していることを想定している.
以降の手順では主開発者が実施するStepのみ分かりやすいように太字を利用している.主開発者・共同開発者,どちらが実施すべき項目かを十分理解して作業をすすめること.
- E1. 共同開発者によるブランチの作成とPush
- E2. 共同開発者による
add_game_result_display
ブランチでの開発及びCommit,Push - E3. 共同開発者によるPull Requestの作成
- E4. 主開発者によるブランチの作成とPush
- E5. 主開発者による
add_total_score
ブランチでの開発及びCommit,Push - E6. 主開発者によるPull Requestの作成
- E7. 主開発者による共同開発者のブランチのレビュー(リモートリポジトリからの
add_game_result_display
ブランチのFetch) - E8.主開発者による(共同開発者の作成した)Pull Requestの
master
ブランチへのMerge - E9. 共同開発者によるレビュー(GithubによるConflictの検知)
- E10. 主開発者によるConflictの解消
- E11. 共同開発者による(主開発者が作成し,Conflictを解消した)Pull Requestのレビュー
- E12. 共同開発者による(主開発者の作成した)Pull RequestのmasterブランチへのMerge
このシナリオでは,仕様にあるとおり,じゃんけんゲームに「勝敗表示」及び「スコア表示」という2つの機能を別々の開発者が追加する.共同開発者が「勝敗表示」機能を,主開発者が「スコア表示」機能を追加する過程において,異常状態が発生する.以降に示す手順に従い,2人での開発と異常状態への対応を実施せよ.
E1. 共同開発者によるブランチの作成とPush
正常系シナリオでも述べた通り,Github flowではmaster
ブランチに対してPull RequestからのMerge以外の方法でファイルの編集を行うことはない.そのため,「勝敗表示」という新しい機能を共同開発者が実装する際には,必ず対応したブランチをローカルに作成しなければならない.
ここで共同開発者は正常系シナリオD4と同様に,ブランチを作成し,それをサーバ側リポジトリにPushする.具体的な手順は下記のとおり.
共同開発者は「
add_game_result_display
」という名前でmaster
ブランチから新しいブランチを作成する.ブランチアイコンをクリックし,Nameに分かりやすいブランチ名(今回は「add_game_result_display
」)を書き,From branchの項目がmaster
になっていることを確認後,「Create new branch」ボタンをクリックする.ブランチが正常に作成できると,Github Desktopが「
add_game_result_display
」ブランチの画面に自動的に切り替わる.この時点で,ユーザのローカルリポジトリに「add_game_result_display
」ブランチが作成されたことになる.Github Desktopの画面から「Publish」ボタンをクリックし,ブランチのPushを行う.Push完了後に,Github上のリポジトリページから「3 branches」(ブランチの数)というリンクをクリックすると,下図のように現在Github上のリポジトリにpushされているブランチの一覧を見ることができるので,
add_game_result_display
ブランチがあることを確認すること.
E2. 共同開発者によるadd_game_result_display
ブランチでの開発及びCommit,Push
Github Desktop上でブランチをadd_game_result_display
にした状態で,「勝敗表示」機能を共同開発者が実装する.ここでは,Gameクラスのフィールド及びgetJankenResult()
メソッドとBoardクラスのupdateCommentArea()
メソッドを修正する.詳細な実装内容を下記に示す.
Gameクラスにint型のwin,draw,loseというフィールドを追加し,
getJankenResult()
メソッドを修正する.修正後のGameクラス全体を下記に示す.class Game { int win=0; int draw=0; int lose=0; String getJankenResult(String hand) { String cpuHand = this.desideCpuHand(); if (hand.equals("Gu") && cpuHand.equals("Gu") || hand.equals("Choki") && cpuHand.equals("Choki") || hand.equals("Pa") && cpuHand.equals("Pa")) { draw++; return "Draw"; }else if (hand.equals("Gu") && cpuHand.equals("Choki") || hand.equals("Choki") && cpuHand.equals("Pa") || hand.equals("Pa") && cpuHand.equals("Gu")) { win++; return "You Win!"; }else if (hand.equals("Gu") && cpuHand.equals("Pa") || hand.equals("Choki") && cpuHand.equals("Gu") || hand.equals("Pa") && cpuHand.equals("Choki")) { lose++; return "CPU Win!"; } return null; } String desideCpuHand() { int cpuHandNum = (int)random(3); if (cpuHandNum == 0) return "Gu"; else if (cpuHandNum == 1) return "Choki"; else return "Pa"; } }
- Boardクラスの
updateCommentArea()
メソッドを下記のように修正する.void updateCommentArea(String comment){ fill(#000000); rect(0,150,450,75); fill(#FFFFFF); textSize(30); textAlign(CENTER); text(comment, 225, 180); textSize(20); String scoreMessage = "Win:"+game.win+" Draw:"+game.draw+ " Lose:"+game.lose; text(scoreMessage, 225, 200); }
- 実装が完了した状態で,プログラムを実行すると下記のような画面が表示され,ゲームを進めるにつれて,勝ち,負け,引き分けの数がカウントされるようになる.必ず正常に実行できるか確認しておくこと.
正常に動作することが確認できしだい,Commit及びPushを行っておくこと.なお,プログラムが正常に動作する状態であれば,それまでに細かくCommit及びPushを行っても構わない.Commit及びPushのやり方は正常系シナリオD5を参考にすること.
E3.共同開発者によるPull Requestの作成
正常系シナリオD6を参考に,Pull Requestを作成する.ここで作成するPull Requestは「add_game_result_display
ブランチで開発した内容を確認してmasterブランチに統合してください」というリクエストを共同開発者から主開発者に対してGithubを介して送るためのものである.
- 共同開発者はGithub Desktopの画面右上にある「Pull Request」という文字をクリックし,下記のPull Request画面を表示する.
- その後,上から順に「from add_game_result_display into master」(add_game_result_displayブランチの内容をmasterブランチに,という意味)であることを確認し,TitleとDescriptionに実装内容を簡単に記す.最後に「Send pull request」ボタンをクリックする.
確認項目
- リポジトリのページからPull Requestを表示させると,下図のように
add_game_result_display
からmaster
へのマージを依頼するPull Requestが作成されていることを確認すること(Github DesktopでPull Request作成後に,「View Pull Request」をクリックすると表示される)
E4. 主開発者によるブランチの作成とPush
正常系シナリオでも述べた通り,Github flowではmaster
ブランチに対してPull RequestからのMerge以外の方法でファイルの編集を行うことはない.そのため,「スコア表示」という新しい機能を主開発者が実装する際には,必ず対応したブランチをローカルに作成しなければならない.
ここで主開発者は正常系シナリオD4と同様に,ブランチを作成し,それをサーバ側リポジトリにPushする.具体的な手順は下記のとおり.
主開発者は「
add_total_score
」という名前でmaster
ブランチから新しいブランチを作成する.ブランチアイコンをクリックし,Nameに分かりやすいブランチ名(今回は「add_total_score
」)を書き,From branchの項目がmaster
になっていることを確認後,「Create new branch」ボタンをクリックする.ブランチが正常に作成できると,Github Desktopが「
add_total_score
」ブランチの画面に自動的に切り替わる.この時点で,ユーザのローカルリポジトリに「add_total_score
」ブランチが作成されたことになる.Github Desktopの画面から「Publish」ボタンをクリックし,ブランチのPushを行う.Push完了後に,Github上のリポジトリページから「3 branches」(ブランチの数)というリンクをクリックすると,下図のように現在Github上のリポジトリにpushされているブランチの一覧を見ることができるので,
add_total_score
ブランチがあることを確認すること.
E5. 主開発者によるadd_total_score
ブランチでの開発及びCommit,Push
Github Desktop上でブランチをadd_total_score
にした状態で,「スコア表示」機能を主開発者が実装する.ここでは,Gameクラスのフィールド及びgetJankenResult()
メソッドとBoardクラスのupdateCommentArea()
メソッドを修正する.詳細な実装内容を下記に示す.
Gameクラスにint型のscoreというフィールドを追加し,
getJankenResult()
メソッドを修正する.修正後のGameクラス全体を下記に示す.class Game { int score=0; String getJankenResult(String hand) { String cpuHand = this.desideCpuHand(); if (hand.equals("Gu") && cpuHand.equals("Gu") || hand.equals("Choki") && cpuHand.equals("Choki") || hand.equals("Pa") && cpuHand.equals("Pa")) { score++; return "Draw"; }else if (hand.equals("Gu") && cpuHand.equals("Choki") || hand.equals("Choki") && cpuHand.equals("Pa") || hand.equals("Pa") && cpuHand.equals("Gu")) { score = score + 2; return "You Win!"; }else if (hand.equals("Gu") && cpuHand.equals("Pa") || hand.equals("Choki") && cpuHand.equals("Gu") || hand.equals("Pa") && cpuHand.equals("Choki")) { score--; return "CPU Win!"; } return null; } String desideCpuHand() { int cpuHandNum = (int)random(3); if (cpuHandNum == 0) return "Gu"; else if (cpuHandNum == 1) return "Choki"; else return "Pa"; } }
- Boardクラスの
updateCommentArea()
メソッドを下記のように修正する.void updateCommentArea(String comment){ fill(#000000); rect(0,150,450,75); fill(#FFFFFF); textSize(30); textAlign(CENTER); text(comment, 225, 180); textSize(20); String scoreMessage = "Score:"+game.score; text(scoreMessage, 225, 200); }
- 実装が完了した状態で,プログラムを実行すると下記のような画面が表示され,ゲームを進めるにつれて,勝ち,負け,引き分けの結果に応じたスコアが表示される.必ず正常に実行できるか確認しておくこと.
正常に動作することが確認できしだい,Commit及びPushを行っておくこと.なお,プログラムが正常に動作する状態であれば,それまでに細かくCommit及びPushを行っても構わない.Commit及びPushのやり方は正常系シナリオD5を参考にすること.
E6. 主開発者によるPull Requestの作成
正常系シナリオD6を参考に,Pull Requestを作成する.ここで作成するPull Requestは「add_game_result_display
ブランチで開発した内容を確認してmasterブランチに統合してください」というリクエストを共同開発者から主開発者に対してGithubを介して送るためのものである.
- 共同開発者はGithub Desktopの画面右上にある「Pull Request」という文字をクリックし,下記のPull Request画面を表示する.
- その後,上から順に「from add_total_score into master」(add_total_scoreブランチの内容をmasterブランチに,という意味)であることを確認し,TitleとDescriptionに実装内容を簡単に記す.最後に「Send pull request」ボタンをクリックする.
確認項目
- リポジトリのページからPull Requestを表示させると,
add_total_score
からmaster
へのマージを依頼するPull Requestが作成されていることを確認すること(Github DesktopでPull Request作成後に,「View Pull Request」をクリックすると表示される) - この時点で下図のように2つのPull Requestが作成されていることを確認すること
以降からがGitを利用する上での異常状態の体験になるため,ここまでが終了してから実施すること.
E7. 主開発者による共同開発者のブランチのレビュー(リモートリポジトリからのadd_game_result_display
ブランチのFetch)
主開発者が共同開発者の開発したブランチ(add_game_result_display
)を確認する.
手順は以下のとおり.
- Github Desktopのブランチリストの中に下図に示すように
add_game_result_display
がある場合,add_game_result_display
を選択し,「Sync」ボタンをクリックする.ない場合は次の手順に従う(ある場合は次の手順は飛ばして良い).
- Github Desktopのブランチリストの中に
add_game_result_display
がない場合,下図に示すように,リポジトリ名を右クリックしてから「Open in Git Shell」をクリックする.Gitのコマンドライン操作画面が開くので,「git fetch」と入力し,Enterキーを叩く.その後,Github Desktopのブランチリストにadd_game_result_display
が表示されるので,add_game_result_display
を選択し,「Sync」ボタンをクリックする
- Github Desktopでブランチを
add_game_result_display
に切り替えた後,Processingからプログラムを実行し,下図のように勝ち,引き分け,負けが正しく表示されることを確認する.- Processing IDEからJanken_学生番号.pdeを実行すれば良い.
注意!
正しく表示されない場合は,正常系シナリオD7を参考に共同開発者にプログラムの修正を行い,Commit/Pushするよう伝えること.さらに,Pushが行われた後,再度E7を実行し,正しくプログラムが実行されることを確認する.
E8.主開発者による(共同開発者の作成した)Pull Requestのmaster
ブランチへのMerge
E7が正常に完了した後,レビューを行った主開発者が共同開発者によって開発されたadd_game_result_display
ブランチのMergeを行う.
正常系シナリオD8を参考に,「勝敗表示機能」に関するPull RequestのページをGithubのリポジトリページから表示し,「Confirm merge」をクリックする.
確認項目
- Merge完了後,Github Desktop上で
master
ブランチを表示し,「Sync」ボタンをクリックする. master
ブランチを「Sync」で更新した後,Processingからプログラムを実行し,下図のように勝ち,引き分け,負けが正しく表示されることを確認する.- Processing IDEからJanken_学生番号.pdeを実行すれば良い.
E9. 共同開発者によるレビュー(GithubによるConflictの検知)
この時点で残っているPull Requestは主開発者によってE6で作成されたスコア表示機能(add_total_score
ブランチ)のみになり,そのPull RequestをGithubのリポジトリページから表示させると下記のようにConflictが検知される.このままではレビュー及びMergeができないため,Pull Requestのコメントとして,Conflict(競合)が発生していること記述し,主開発者に伝える.
E10. 主開発者によるConflictの解消
このConflictはadd_total_score
の修正内容が直前にCommit/Pushされたadd_game_result_display
ブランチの修正内容と重なってしまったために発生している.この演習ではわざと行ったが,実際の開発においても同様の状況が発生することは十分に考えられる.
主開発者がConflictを解消するためには,最新のmaster
ブランチの内容を主開発者が開発したadd_total_score
ブランチに取り込み,実装を修正してCommit/Pushをやり直す必要がある.
具体的な手順を以下に示す.
C1. master
ブランチの更新
下図に示すように,Github Desktop上でmaster
ブランチを表示し,「Sync」をクリックすることで,最新のmaster
ブランチの内容を取得する.
C2. ローカルリポジトリでのmaster
ブランチのadd_total_score
ブランチへのMerge
C1終了後,更新されたmaster
ブランチの内容をadd_total_score
ブランチにMergeする.具体的には下図に示すとおり,Github Desktop上でadd_total_score
ブランチを表示し,「Update from master」をクリックする.master
ブランチの内容とadd_total_score
ブランチの内容はConflictするため,「Unable to merge」画面が表示される.ここではそのまま「View conflicts」をクリックする.
C3.プログラムの修正
C2を実施すると,Github Desktop上でどこにConflictがあるのかを示してくれる.さらに, ソースコード中にConflict箇所を示す下図のような文字列が挿入される.
この例では,Boardクラスの22行目がadd_total_score
で実装された内容であり,24行目がmaster
ブランチの内容であることが示されており,この2つの行がConflictすることを表している.
この演習では,勝敗表示とトータルスコア表示の両方を実装することが目標であるため,Boardクラスを下記のように修正する.
class Board {
void updateSelectArea() {
PImage gu = loadImage("gu.png");
PImage choki = loadImage("choki.png");
PImage pa = loadImage("pa.png");
image(gu, 0, 0, 150, 150);
image(choki, 150, 0, 150, 150);
image(pa, 300, 0, 150, 150);
}
void updateCommentArea(String comment){
fill(#000000);
rect(0,150,450,75);
fill(#FFFFFF);
textSize(30);
textAlign(CENTER);
text(comment, 225, 180);
textSize(20);
String scoreMessage = "Score:"+game.score + " Win:"+game.win+" Draw:"+game.draw+ " Lose:"+game.lose;
text(scoreMessage, 225, 200);
}
void updateResultArea(String result) {
fill(#000000);
rect(0,225,450,75);
fill(#FFFFFF);
textSize(45);
textAlign(CENTER);
text(result, 225, 260);
}
}
同様にGameクラスでは下図のように示されていた場合,3行目(add_total_score
ブランチ)と5~7行目(master
ブランチ)がConflictしていることを表している.
ここでも勝敗表示機能とトータルスコア表示機能が両立するように,Gameクラスを下記のように修正する.
class Game {
int score=0;
int win=0;
int draw=0;
int lose=0;
String getJankenResult(String hand) {
String cpuHand = this.desideCpuHand();
if (hand.equals("Gu") && cpuHand.equals("Gu")
|| hand.equals("Choki") && cpuHand.equals("Choki")
|| hand.equals("Pa") && cpuHand.equals("Pa")) {
score++;
draw++;
return "Draw";
}else if (hand.equals("Gu") && cpuHand.equals("Choki")
|| hand.equals("Choki") && cpuHand.equals("Pa")
|| hand.equals("Pa") && cpuHand.equals("Gu")) {
score = score + 2;
win++;
return "You Win!";
}else if (hand.equals("Gu") && cpuHand.equals("Pa")
|| hand.equals("Choki") && cpuHand.equals("Gu")
|| hand.equals("Pa") && cpuHand.equals("Choki")) {
score--;
lose++;
return "CPU Win!";
}
return null;
}
String desideCpuHand() {
int cpuHandNum = (int)random(3);
if (cpuHandNum == 0) return "Gu";
else if (cpuHandNum == 1) return "Choki";
else return "Pa";
}
}
主開発者が2つのクラスのソースコードを修正した後,Processing IDEからプログラムを実行し,下記のようにスコアと勝敗数両方が正しく表示されることを確認する.
C4.Conflict解消後のプログラムのCommit/Push
C3でプログラムが正常に動作することを確認後,Github DesktopからCommitを行う.Commitする2つのファイルをチェックし,CommitのTitleとDescriptionを記述し,「Commit to add_total_score」をクリックする.Commitが正常に完了後,画面右上の「Sync」ボタンをクリックし,サーバにPushしておくこと.
確認項目
- Push完了後に,主開発者が作成したPull Requestを確認すると,下記のようにConflictが解消され,「This branch has no conflicts」と表示が変化していることが分かる.
E11.共同開発者による(主開発者が作成し,Conflictを解消した)Pull Requestのレビュー
E7と同様に,共同開発者が主開発者の作成したPull Request(add_total_score
ブランチ)のレビューを行う.
手順はE7と同様.
Github Desktopのブランチリストの中に
add_total_score
がある場合,add_total_score
を選択し,「Sync」ボタンをクリックする.ない場合は次の手順に従う(ある場合は次の手順は飛ばして良い).Github Desktopのブランチリストの中に
add_total_score
がない場合,リポジトリ名を右クリックしてから「Open in Git Shell」をクリックする.Gitのコマンドライン操作画面が開くので,「git fetch」と入力し,Enterキーを叩く.その後,Github Desktopのブランチリストにadd_total_score
が表示されるので,add_total_score
を選択し,「Sync」ボタンをクリックするGithub Desktopでブランチを
add_total_score
に切り替えた後,Processingからプログラムを実行し,下図のように勝ち,引き分け,負けが正しく表示されることを確認する.- Processing IDEからJanken_学生番号.pdeを実行すれば良い.
E12. 共同開発者による(主開発者の作成した)Pull RequestのmasterブランチへのMerge
E11が正常に完了した後,レビューを行った共同開発者が主開発者によって開発されたadd_total_score
ブランチをmaster
ブランチにMergeする.
正常系シナリオD8及び本シナリオE8を参考に,「トータルスコア表示機能」に関するPull RequestのページをGithubのリポジトリページから表示し,「Confirm merge」をクリックする.
確認項目
- Merge完了後,Github Desktop上で
master
ブランチを表示し,「Sync」ボタンをクリックする. master
ブランチを「Sync」で更新した後,Processingからプログラムを実行し,下図のようにトータルスコア及び勝ち,引き分け,負けが正しく表示されることを確認する.- Processing IDEからJanken_学生番号.pdeを実行すれば良い.