どぼじょのIT学習ブログ

高専卒土木女子がIT業界を目指してお勉強。

楽々ERDレッスン

『楽々ERDレッスン』(翔泳社)を読みました!
データベース設計の本です📖

目次

1.使用書籍

www.shoeisha.co.jp

2.DB設計総論

2-1. 正規化

DB設計において、One Fact in One Place というのが要点になります。
簡単にいうと、重複を排除して、1つのデータの置き場所を1箇所に整理するような感じです。
これを実現するために正規化という手法があります。

2-2. 正規化の手順(例)

商品の伝票を例にした正規化の手順の例です。

  1. 項目と値を全て列挙
  2. 繰り返し部分の切り出し
  3. 従属性の追加
  4. 冗長性の排除

例えばはじめに項目を伝票番号、日付、顧客名、商品名1、単価1、数量1、金額1、合計金額と列挙し、値を全て書き出します。
次に商品名1、商品名2、…など、繰り返すものを切り出します。
従属性の追加とは、商品ごとに単価が決まっている場合、商品名と単価をくっつけることです。
冗長性の排除とは、金額、合計金額は自明であるため削除するといったことです。

また、レコードの中身とは関係なくレコードの存在を表現するために、IDを定義することがあります。

  1. IDの割り付け
  2. ERDで表現

伝票ID、顧客ID、商品IDを定義し、ERD(Entity Relationship Diagram)という図で表現するという流れですが、詳しくは今後勉強です🙂

2-3. キー

キーとは、膨大なデータの中からあるデータを特定するための識別子です。
キーの定義の善し悪しでデータベース設計のクオリティが大きく左右されるそうです🤨
一般的には以下のようなものがあります。

キー 役割
主キー
(primary key)
・候補キーの中から何らかの意味的に選択された、インスタンスを特定可能な識別子
ユニークキー ・エンティティ内のインスタンスをそれぞれに特定可能な識別子
・実装上はユニークインデックス
候補キー ・エンティティ(箱)内のインスタンスをそれぞれに特定可能な識別子の「すべて」
・実装上はインデックス
外部キー
(foreign key)
・エンティティをまたがってのインスタンス同士の関係
・参照整合性制約

3.DB設計の手順

DB設計の手順は以下のとおりです。

  1. 大まかにブロック分けを行う(業務単位か部門単位)
  2. それぞれのブロックごとにイベント系を洗い出す
  3. イベント系に対する正規化を行って、リソース系を洗い出す
  4. リソース系に対する分類の洗い出しを行って、リソース系の正規化を行う
  5. ブロック間でリソース系の統合を行い、さらに正規化を行う
  6. 導出系の整理をして、最終的な正規化を行う

4.感想など

この本とってもわかりやすいです。
最低限SQLの基礎を知っている方向けの本でしたが、語彙が豊富で表現が面白く、知的で、小説を読んでいるようでした!(わたしの語彙力が残念で申し訳ありません)
頭の良い人にやさしく教えてもらっている気分になれるのでおすすめです💪笑

SQLの基本

本日は SQL について勉強します!
データベースについては以前実務でFileMakerを使っていたので、単語が全く分からないわけではないため、テーブルとかの用語は解説を割愛いたします🙇‍♀️

目次

1.SQLとは

SQL(Structured Query Language)とは、データベースを操作するための言語のことです。
以前PostgreSQLというものを学習しましたが、だいぶ忘れています😗笑
SQLには ISO(国際標準化機構)で定められた標準規格があるそうで、ISO に準拠した SQL標準SQLと言います。

2.SQLの分類

SQLは、定義操作制御の3つに分類されます。

2-1. DDL(Data Definition Language)

DDLデータ定義言語です。以下のようなコマンドがあります。

コマンド 機能
CREATE データベースやテーブルなどを作成する
DROP データベースやテーブルなどを削除する
ALTER データベースやテーブルなどの構成を変更する

削除はDELETEではないのですね…😐
DELETEは次に出てくるので間違えないように注意ですね!

2-2. DML(Data Manipulation Language)

DMLデータ操作言語です。以下のようなコマンドがあります。

コマンド 機能
SELECT テーブルから行を検索する
INSERT テーブルに新規行を登録する
UPDATE テーブルの行を更新する
DELETE テーブルの行を削除する

2-3. DCL(Data Control Language)

DCLはデータ制御言語です。以下のようなコマンドがあります。

コマンド 機能
COMMIT データベースに対して行った変更を確定する
ROLLBACK データベースに対して行った変更を取り消す
GRANT ユーザーに操作の権限を与える
REVOKE ユーザーから操作の権限を奪う

3.SQLの書き方

SQLの書き方にはルールがあります。

  • SQL文の最後にセミコロン ; をつける
  • キーワードに大文字/小文字の区別はない
  • 定数はシングルクォーテーション ‘ で囲む

4.操作方法(sqlite3)

わたしのmacbookには sqlite3 がインストールされているので、これを使って操作をしてみます!
(いつかの勉強会でいつの間にかインストールしてたようです笑)

4-1. 接続

データベースに接続します。データベースが無い場合、新規作成になります。
今回はtestという名前のデータベースを作成します!

$ sqlite3 test.sqlite3

f:id:mistyrinth:20190315205802p:plain

4-2. CREATE

テーブルの新規作成をします。
文章で説明するとものすごくわかりにくいと思うので、実際に作ったもの載せます😂
f:id:mistyrinth:20190315220348p:plain
途中で改行を入れたとしても、先程のルールのとおり、SQL文の最後はセミコロン;です。
なのでキャプチャは6行に分かれていますが、SQL文としては1文です👀

CREATE TABLEのあとにテーブル名shopping_listを書き、その後に括弧( )の中に列名、データ型、制約の3セットが並んでいます。
列名はidnamepricenoteの4つがあります。
データ型は以下のように設定できます💡

データ型 意味
INTEGER 整数(小数は入らない)
CHAR 固定長文字列
指定した最大長に満たない場合は後ろを半角スペースで埋める
VARCHAR 可変長文字列
指定した最大長に満たない場合は何もしない
DATE 日付(年月日)

VARCHARTEXTでも良いみたいですが、VARCHARだと最大長がマルチバイト文字に対応するとか、TEXTだと最大長はバイト数で決まるとか違いがあるそうです。
今はどっちでも良いかな…?

制約がNOT NULLの場合、必ずデータが格納されていないといけないという意味になり、無記入ではエラーになります🧐
最後の PRIMARY KEY は、特定のデータを指定するときの主キーになります。 そのため、主キーは重複してはいけません。
例えば「ラーメン」という商品を2つ登録するとしても、1つめのラーメンと2つめのラーメンを見分けるために異なる主キーを使います。
ここではidを主キーとしています✨

4-3. トランザクション

データベースにおけるトランザクション(transaction)とは、簡単に言うとデータベースの複数の操作を一括で更新することです。
先程作った空のテーブルにデータを入れていきます💪💪

BEGIN TRANSACTION;トランザクションを開始します。
その後INSERTなどでデータを触ったら、最後にCOMMIT;で変更を一括で反映させます。
トランザクションの終了はEND TRANSACTION;です👏
もし途中で間違えたら、COMMITではなくROLLBACKを使って変更を破棄します💡
なんとなく感覚的にわかりやすいです〜🐾

4-4. INSERT

トランザクションを行って、INSERTで2行追加しました!
f:id:mistyrinth:20190315222211p:plain
最後にCOMMIT;を行った時点で、データベースに反映されます。
DB Browser for SQLiteというソフトをインストールしているので、視覚的に確認することができます!
f:id:mistyrinth:20190315222324p:plain

4-5. SELECT

SELECTは検索コマンドです。
今作ったtest.sqlite3にはほとんどデータが格納されていませんが、実際データベースは多大なデータを格納します。
この中から検索する時に使うため、重宝されるコマンドみたいです🎉
f:id:mistyrinth:20190315222556p:plain
*を使うと全てを表示してくれるみたいですね〜!

4-6. DELETE

DELETEは行を削除するコマンドです。
先程追加したorangeの行を削除します。
f:id:mistyrinth:20190315223708p:plain
ブラウザで、行が消えているのが確認できます😶
f:id:mistyrinth:20190315223747p:plain

4-7. UPDATE

UPDATEは行を更新するコマンドです。
f:id:mistyrinth:20190315224101p:plain
単価を1.08倍にしました😊
f:id:mistyrinth:20190315224123p:plain

Rubyでwcコマンドを作った

lsコマンドに続き、Rubyでwcコマンドを作りました〜!
課題なのでカンニング防止のためコードは公開できないのですが、学んだことまとめます💪

目次

1.wcコマンドとは

wcコマンドは、指定したファイルの行数・単語数・バイト数を表示してくれるコマンドです🌱
f:id:mistyrinth:20190315193802p:plain
上記のとおり、fileAは7行、6単語、43バイトであることがわかります✨
7行で6単語というのは、最後に空白行があるからです。ややこしくてすみません笑
f:id:mistyrinth:20190315194028p:plain
なお、macのwcコマンドのソースコードこちらです。

2.wcコマンド成果

複数のコマンドライン引数に対応しました🎉
f:id:mistyrinth:20190315192844p:plain

オプションは-l-w-cに対応しました。
f:id:mistyrinth:20190315193003p:plain

標準入力にも対応👏
f:id:mistyrinth:20190315193101p:plain

3.学んだこと

3-1. コマンドライン引数

lsコマンドでもコマンドライン引数は扱いましたが、なんとなくで出来てしまっていました💦
wcコマンドはそうはいかなかったので、以前よりは扱えるようになったと思います。
RubyにはARGVという、コマンドライン引数を配列にしたものがあります。
例えば$ wc file1 file2ならARGV = ["file1", "file2"]となります。

3-2. 標準入力

Rubyには標準入力を扱うための変数があることがわかりました!

docs.ruby-lang.org

$stdinでもSTDINでもどちらでも良いそうです。
配列のARGVと違って変数なので、それ自体が値を持っているのではないことや、標準入力が代入されるということが注意点でした。

3-3. マルチバイト文字の単語数

これが一番苦戦したのですが、マルチバイト文字を含むファイルを指定すると単語数がずれてしまうことがありました…😭
単語数というのは、wcコマンドにおいては空白文字で区切られた文字列の数と定義されています。
man wcに書いてありました👀

A word is defined as a string of characters delimited by white space characters.
White space characters are the set of characters for which the iswspace(3) function returns true.

そしてこの空白文字の定義はiswspace関数が true であることなんです。
更に、iswspace関数が true を返す値というのは以下のとおりです。

- 空白' '
- 改頁 \f
- 改行 \n
- 復帰 \r
- 水平タブ \t
- 垂直タブ \v

ここまでは良いのですが、これらとマルチバイト文字が何の関係があるかというと、マルチバイト文字はバイト文字に変換すると、ノーブレークスペースというのが含まれていることがあるそうです😳
例えば「配列」のの字にノーブレークスペースが含まれます。

text = "配 列"
text.bytes { |b| print "0x" + b.to_s(16) + " "}
#=> 0xe9 0x85 0x8d 0x20 0xe5 0x88 0x97

配 列という文字列に対して、空白で区切った文字列の数を単語数とすると、2単語ですよね🙂
でもこれオリジナルのwcコマンドだと3が返ってくるんです…😖
をバイト文字にすると0xe9 0x85 0x8dで、このうちの0x85が iswspace 関数で true になってしまうからです。
このような目に見えないスペースをノーブレークスペースと言うそうです。
0x20は普通の半角スペースで、改行は0xa0になります。

ノーブレークスペースをカウントするために、マルチバイト文字をバイト文字列に変換し、ノーブレークスペースの数だけ単語数を増やすことになりました。
バイト文字列というのがよくわかっていなかったのですが、先頭の0xは共通みたいです😶
bytesメソッドで文字列をバイトの数値に変換できるので、それを更に16進数に変換し、0xに続けます。
UTF-8 とかの文字コード?もぼんやりとしか分かっていないので、難しかったです〜〜💀💀💀
分かりやすいサイトとかあったら教えてほしいです…。

Rubyの配列コピーの種類

Rubyの配列コピーについて試したので記録です🙌

目次

1. 配列のコピーの種類

配列をコピーすると同じ要素を参照するのか?他方の要素の変更の影響を受けるのか?というのが曖昧だったので、動作を試してみました!
オブジェクトIDはそのままだと桁が大きく読みづらいので、10000で割った余りの数で比較しています。
結果的には以下のような違いがあるみたいでした⛱

コピーの種類 配列のID 要素のID 要素の変更の影響
浅いコピー 異なる 同じ 受けない
深いコピー 異なる 異なる 受けない
代入 ( a = b ) 同じ 同じ 受ける

2.浅いコピー

2-1. コード

org = ["あいうえお", "abcde", "12345"]
puts "org = #{org} (元の配列)"
puts "配列 org ID:#{org.object_id % 10000}"
puts "要素 org[0] ID:#{org[0].object_id % 10000}"

# shallow copy
shal = org.dup
puts "shal = #{shal} (浅いコピー)"
puts "配列 shal ID:#{shal.object_id % 10000}"
puts "要素 shal[0] ID:#{shal[0].object_id % 10000}"

org[0] = "アイウエオ"
puts "org[0]の値を \"#{org[0]}\" に変更"
shal[1] = "ABCDE"
puts "shal[1]の値を \"#{shal[1]}\" に変更"

puts "org = #{org}"
puts "shal = #{shal}"
puts "配列 org ID:#{org.object_id % 10000}"
puts "配列 shal ID:#{shal.object_id % 10000}"
puts "要素 org[0] ID:#{org[0].object_id % 10000}"
puts "要素 shal[0] ID:#{shal[0].object_id % 10000}"
puts "要素 org[1] ID:#{org[1].object_id % 10000}"
puts "要素 shal[1] ID:#{shal[1].object_id % 10000}"
puts "要素 org[2] ID:#{org[2].object_id % 10000}"
puts "要素 shal[2] ID:#{shal[2].object_id % 10000}"

2-2. 結果

f:id:mistyrinth:20190304173243p:plain

3.深いコピー

3-1. コード

org = ["あいうえお", "abcde", "12345"]
puts "org = #{org} (元の配列)"

# deep copy
deep = Marshal.load(Marshal.dump(org))
puts "deep = #{deep} (深いコピー)"

puts "配列 org ID:#{org.object_id % 10000}"
puts "配列 deep ID:#{deep.object_id % 10000}"
puts "要素 org[0] ID:#{org[0].object_id % 10000}"
puts "要素 deep[0] ID:#{deep[0].object_id % 10000}"
puts "要素 org[1] ID:#{org[1].object_id % 10000}"
puts "要素 deep[1] ID:#{deep[1].object_id % 10000}"
puts "要素 org[2] ID:#{org[2].object_id % 10000}"
puts "要素 deep[2] ID:#{deep[2].object_id % 10000}"

3-2. 結果

f:id:mistyrinth:20190304173330p:plain

4.代入

4-1. コード

org = ["あいうえお", "abcde", "12345"]
puts "org = #{org} (元の配列)"

# substitution
sub = org
puts "sub = #{sub} (代入)"

puts "配列 org ID:#{org.object_id % 10000}"
puts "配列 sub ID:#{sub.object_id % 10000}"

org[0] = "アイウエオ"
puts "org[0]の値を \"#{org[0]}\" に変更"
sub[1] = "ABCDE"
puts "sub[1]の値を \"#{sub[1]}\" に変更"

puts "org = #{org}"
puts "sub = #{sub}"
puts "配列 org ID:#{org.object_id % 10000}"
puts "配列 sub ID:#{sub.object_id % 10000}"
puts "要素 org[0] ID:#{org[0].object_id % 10000}"
puts "要素 sub[0] ID:#{sub[0].object_id % 10000}"
puts "要素 org[1] ID:#{org[1].object_id % 10000}"
puts "要素 sub[1] ID:#{sub[1].object_id % 10000}"
puts "要素 org[2] ID:#{org[2].object_id % 10000}"
puts "要素 sub[2] ID:#{sub[2].object_id % 10000}"

4-2. 結果

f:id:mistyrinth:20190304173418p:plain

Rubyでlsコマンド作成

久しぶりの投稿ですが、勉強してなかったわけではありません!!笑
Rubyでlsコマンドを作っていました。
ようやくできたので、学んだことなど記録します〜😊

目次

1.経緯

フィヨルドブートキャンプの課題で、 ls コマンドを作ることになりました。
ls コマンドは、ターミナルで使えるLinuxのコマンドのひとつで、今いるディレクトリに入っているファイルを一覧で表示するコマンドです💡
ちなみに他の方も課題で作るため、作成したコードは公開できません💦

2.成果

オプションなしのlsに加え、-a-r-lオプションに対応しました💡
macのlsコマンドと比較して、以下のとおり同じ出力になりました🎉🎉

ls (オプションなし)

f:id:mistyrinth:20190222183846p:plain

ls -a

f:id:mistyrinth:20190222183902p:plain

ls -r

f:id:mistyrinth:20190222183916p:plain

ls -l

f:id:mistyrinth:20190222183933p:plain

ls -arl (オプション同時実行)

f:id:mistyrinth:20190222183950p:plain

3.新しく学んだこと

これを作るのに学んだことは沢山ありますが、主なものを紹介します!

3-1. オプションのつけかた

optparseというものを使いました。
参考サイト多すぎて紹介しきれないのですが、正直言って未経験者にとって本気で参考になったサイトってひとつも無かったような…😭
いろんなサイトの情報をかいつまんで自分なりに解釈して、どのサイトにも見かけなかった方法で作ってしまいました。使い方が合ってるのかわかりませんが、実行できたのでとりあえず結果オーライです💪笑

3-2. クラス定義、メソッド定義

今まではクラス定義やメソッド定義は概念として「こういうのがあるのかー」程度に知っていたのですが、実際にどういった場面で使うのか全然分かりませんでした!
最初はクラスもメソッドも定義せずにベタ打ちで書き始めて、複雑になってきた頃にようやくメソッドを定義しました。
実際のところ、クラスを定義する過程って「こういうオブジェクトを作りたい」→「クラス定義する(クラスメソッドも定義する)」→「クラスからオブジェクトを作る」という感じでした。分かりづらい…??🤨
クラスを定義しないとmainクラスのオブジェクトになってしまうので、不都合が出てきてしまいます。
このあたりもうちょっと学習してちゃんと説明できるようになりたいです!!

3-3. リファレンスマニュアル

gem を使っていないので、配列を作ったりファイルの情報を取得したりという細かいことは、ほとんどリファレンスマニュアルを見ながらできました🎉

3-4. その他

わからないところを時間掛けて調べて試して、95%くらい自力で考えて作ってみたので、だいぶ進歩したな!と感じています✨
他の方にいただいたアドバイスは「クラスを作って最後にオブジェクトを呼び出せばいける」ということと「mapメソッドが便利」ということだけでしたが、これが無ければかなり厳しかったですー!
アドバイスありがとうございました!
いきなり完成形を目指すのは難しいので、まず手始めに簡単なところから作っていったり、部分的に別ファイルに作って動作検証したりしたのが良かったです。
構造がイメージできればそんな手間かける必要ないのですが…😖

次はwcコマンドの作成にかかります!🙌

Git-it

今回はGithubのお勉強ということで、Git-itをやってみます!

目次

1.Git-itインストール

Git-itのアプリは以下のページからダウンロードできます。Macの方はGit-it-darwin-x64です😊

github.com

インストールしたアプリを開くと、スタート画面が出てきます。
11ステップに分けて学べるみたいですね👀 言語は日本語に設定できます✨
f:id:mistyrinth:20190116160103p:plain

2.Git-it開始

GET STARTED!から開始します。
ちなみに私は既にGitのインストールとGithubのアカウント作成は済んでいるので、終わっているところは飛ばしながらやっていきます。

2-1. Gitをインストールして設定をする

既に終わっているので飛ばします〜!
参考記事:Git入門 part1 / Gitの基本

2-2. ローカルのrepositoryを作成

ローカルリポジトリを作成します。
hello-worldという名前のディレクトリを作成し、プロジェクトを初期化して新しいGitインスタンスを作成します。
このあたりも既に学習済みなのでさくさく進めていきます💪
f:id:mistyrinth:20190116161507p:plain

2-3. ステータスを確認して、コンテンツを追加してcommitをする

作成したリポジトリの中にテキストファイルを作成します。
readme.txtというファイルを作成し、Helloとだけ書きます✋

f:id:mistyrinth:20190116162624p:plain

statusコマンドでファイルに変更が加わっていることを確認したら、addコマンドでコミットをライブラリに追加し、commitコマンドでコミットします💡
f:id:mistyrinth:20190116163201p:plain

更に、readme.txtに2行目(World!)を追加します。
diffコマンドで最後にコミットした内容と現在の内容を照らし合わせ、差分を確認できます👀
差分を確認したら、先程と同様にコミットします✨
f:id:mistyrinth:20190116164825p:plain

2-4. GitHubのアカウントを作成

Githubのアカウントは持っているのですが、以下のコマンドでGitにGithubのユーザー名を登録できるようなので、やってみます!

$ git config --global user.username ユーザー名

f:id:mistyrinth:20190116165516p:plain

登録できました!

2-5. ローカルのrepositoryをGitHub.comのrepositoryに接続

Githubにログインして、新規リポジトリを作成します。
このとき、ローカルリポジトリhello-worldと同じ名前を指定します💪💪
f:id:mistyrinth:20190116165858p:plain

ローカルリポジトリ側の操作で、リモートリポジトリ(Github)に Push します。
リモートリポジトリにoriginという名前をつけ、masterブランチに Push です😇
f:id:mistyrinth:20190116172258p:plain
参考記事:Git入門 part2 / リポジトリの共有, 変更履歴の統合

2-6. オープンソースのrepositoryをforkしてcloneする

今度はリポジトリのフォーク(fork)をやってみます!
フォークとは、対象のリポジトリのコピーをリモートリポジトリ(Github)のひとつとして使うようにすることです。
この時点ではGithub上でリポジトリの複製をしているだけで、ローカルリポジトリには対象のリポジトリはありません🙁

ここでは、以下のリポジトリをフォークします!

github.com

f:id:mistyrinth:20190116215549p:plain

右上のForkボタンを押します👆
読み込みのアニメーションが現れたあと、フォーク完了です🎉
f:id:mistyrinth:20190116215722p:plain

次に、フォークしたリポジトリをローカルリポジトリにクローンします。
このとき、ローカルリポジトリhello-worldディレクトリ)にいる場合は外に出ます👣
以下のコマンドでリポジトリをクローンすることができます。

$ git clone GithubのURL

また、元々のリポジトリ(フォーク元)に変更が加わった場合に簡単に Pull できるように、元々のリポジトリに名前をつけておきます。
名前はなんでも良いのですが、upstreamという名前をつけることが多いみたいです🙂
f:id:mistyrinth:20190116221146p:plain

2-7. 新機能・修正のためにbranchを作成

ブランチについては学習済みのため、割愛します〜!
参考記事:Git入門 part3 / ブランチ

GitHubの機能として、gh-pagesという名前のブランチにあるファイルを、自動的に静的なWebサイトとしてホストしてくれるそうです。
今回フォークしたプロジェクトはWebサイトを作るためのものなので、メインブランチの名前はmasterではなくgh-pagesです😶
また、このようなサイトのURLは以下のようになっています。

http://githubusername.github.io/repositoryname

早速ブランチを作成しますが、その前に今どこのブランチにいるのかをstatusコマンドで確認しておきます。
f:id:mistyrinth:20190116222621p:plain
gh-pagesという名前のブランチにいることが分かりましたね!!Webサイトを作るためのメインブランチです。

新しくadd-mistyrinthという名前のブランチを作成し、チェックアウトします。
f:id:mistyrinth:20190116223022p:plain

クローンしたpatchwork内にある既存のcontributorsという名前のディレクトリ内に、新しくadd-mistyrinth.txtというファイルを作成します。
中身はmistyrinthというユーザー名のみ記入しました🙃
このテキストファイルをaddcommitコマンドによりコミットします。
最後にこの変更をGitHub上の自分のリポジトリにPushします!
一連の流れは以下のとおりです☀️
f:id:mistyrinth:20190116224509p:plain

2-8. Collaboratorを追加して作業を同期する

GitHub上で、他の人のリポジトリにアクセスして編集する権限を持つ人をコラボレーター(Collaborators)と言います。
コラボレーターはSettingタブから簡単に追加できます😊
追加したら相手に通知がいき、承認されればコラボレーターになっていただけます!
f:id:mistyrinth:20190117142906p:plain

2-9. 修正をGitHub.comと同期するためにpushとpullを行う

同じプロジェクトで他の人もファイルに修正を加えている場合などに、ファイルを pull することで、最新の状態を取り込むことができます⛱

参考記事:Git入門 part2 / リポジトリの共有, 変更履歴の統合

f:id:mistyrinth:20190117152904p:plain
何も変更がされていなければ、Already up to date.と表示されます✨

2-10. Pull requestを作成

フォークしたリポジトリに変更や修正を加えたら、変更元のリポジトリの所有者に対して、自分が行った変更や修正を元のリポジトリにも反映してもらえるよう、プルリクエストを送ることができます。
参考記事:Git入門 part5 / Pull Request

元のリポジトリにプルリクエストを送ります!
f:id:mistyrinth:20190117155539p:plain

変更箇所は以下のとおりでしたね〜🙃
f:id:mistyrinth:20190117155601p:plain

相手がチェックして問題が無ければプルリクエストがマージされます💡
f:id:mistyrinth:20190117160050p:plain

2-11. Branchをmergeしてdelete(削除)する

プルリクエストがマージされたら、作業用のブランチは不要になりますね。
整理のため、変更を自分のフォークバージョンにもアップデートします。
まず、自分のローカルリポジトリのメインブランチgh-pagesにマージします🙌
その後不要になったブランチadd-mistyrinthは削除し、リモートリポジトリに push します😊
f:id:mistyrinth:20190117161130p:plain

これにより、Github上のadd-mistyrinthブランチも削除され、ブランチはメインブランチの1本だけになります🎉

また、フォーク元のリポジトリupstream)の変更を Pull すると、最新にアップデートされてます。

f:id:mistyrinth:20190117161834p:plain
他のユーザーさんたちもGit-itやってますね笑

Git-itは以上です〜!🧚‍♀️

Git入門 part5 / Pull Request

本日はサルでもわかるGit入門 プルリクエスト編です!

目次

1.プルリクエス

本日学習するプルリクエスとは、Githubなどで利用できる機能で、ローカルリポジトリでの変更を他の開発者に通知する機能です💡
チームで開発をする時に、作業内容をレビュー担当者・マージ担当者などの関係者に通知し、確認してもらうといった使い方ができます😊
自分で作った成果品を、客先に納品する前に上司に確認してもらうようなイメージですね。
プルリクエストの利用により、最終的にマージされるソースコードの品質を高くすることができます。

プルリクエストは一覧で表示され、未完了のプルリクエストを漏れなく確認できます。
プルリクエスト上では、担当者同士でコメントのやりとりをして議論できます。更に、対象のブランチにプッシュされたコミットは、自動的にプルリクエスト上に反映されます。

プルリクエストを利用した開発プロセスは、以下のとおりです。

プロセス 開発者 レビュー・マージ担当者
1 作業対象のソースを clone または pull
2 作業用ブランチを作成
3 開発作業(機能追加や改修)
4 push
5 プルリクエストを作成
6 プルリクエストから変更を確認しレビュー
7-1 修正が必要なら開発者にフィードバック
(プロセス3へ戻る)
7-2 修正が不要ならマージ
7-3 プルリクエスト自体が不要ならクローズ

2.チュートリアル

早速チュートリアルに入ります🙂
JavaScriptで配列だけが準備されている状態のソースコードに、リストの内容をソートする処理を追加するという内容です。
BacklogとGitHubが選択できるので、Githubでやってみます!

2-1. サンプルリポジトリの準備

まずはGithubにログインし、新規リポジトリを作成します。

f:id:mistyrinth:20190116105712p:plain

作成したリポジトリの中に、以下のようなjsファイルを作成します。

f:id:mistyrinth:20190116134915p:plain

2-2. 開発ブランチでの修正

次に、作業するためのブランチを作成します💪
add-sort-funcというブランチを作成し、切り替えます。
f:id:mistyrinth:20190116140039p:plain

ブランチを切り替えたら、先程作成したjsファイルを修正します🖋
f:id:mistyrinth:20190116140230p:plain

コメントを追加してコミットします。
f:id:mistyrinth:20190116140351p:plain

2-3. プルリクエストの作成

リポジトリのトップに戻ると、直近 Push されたブランチが表示されるので、Compare & pull requestを実行します💡
f:id:mistyrinth:20190116140657p:plain

実行すると、次のような画面が表示されます。スクロールして画像2枚に分かれています🙂
f:id:mistyrinth:20190116140922p:plain
f:id:mistyrinth:20190116140932p:plain

上のほうにbase: mastercompare: add-sort-funcと書かれていますね😶
これは、baseがプルリクエストをマージする対象のブランチ、compareがプルリクエストをマージしてもらうブランチを指しています。
更に2枚目のキャプチャは、baseに対してcompareを比較し、10行追加されていることが分かりますね✨
次はCreate pull requestボタンを押します。
f:id:mistyrinth:20190116141620p:plain

これで他の担当者にレビューしてもらうことができるようになりました!🎉

2-4. レビューとマージ

プルリクエストが作成されたら、今度はレビュー担当者がFiles changedタブから変更内容を確認します。
f:id:mistyrinth:20190116141836p:plain

修正してほしい箇所があった場合、該当行の左端にある+からコメントを追加することができます😳便利〜!
f:id:mistyrinth:20190116142407p:plain

自作自演になってしまいますが、修正指示がきたので修正し、再度コミットを行います。
f:id:mistyrinth:20190116142736p:plain

2-5. 画面上でマージ

レビュー担当者は、再度レビューした結果、問題が無ければマージします👌
f:id:mistyrinth:20190116143155p:plain

Merge pull requestを押すと、以下のようにコメントを書くことができます。
f:id:mistyrinth:20190116143303p:plain

コメントは「修正ありがとうございました」などなんでもOKです😊
コメントを書いてConfirm mergeを押すと、マージされます😆✨
f:id:mistyrinth:20190116143412p:plain

3.マージできない場合は?

3-1. 競合の発生

練習のため、別の開発者との競合が発生して、マージできない状況を作ってみます🙁
開発者Aが先程の等価演算子==を使用し、開発者Bが厳密等価演算子===を使うとします。
条件は先程と同じなので、再度新規リポジトリを作成してmasterブランチにjsファイルを作成します🖋
f:id:mistyrinth:20190116144936p:plain

開発者Aが作業するためのadd-sort-func1というブランチと、開発者Bが作業するためのadd-sort-func2というブランチを作成します。
add-sort-func1には、等価演算子==を使ってコードを書き足します。
f:id:mistyrinth:20190116145149p:plain

先程のチュートリアルと同様に、Compare & pull requestからプルリクエストを作成し、修正が無いものとしてマージします!
f:id:mistyrinth:20190116145458p:plain

続いて、ブランチをadd-sort-func2に切り替えて、厳密等価演算子===を使ってコードを書き足します。
f:id:mistyrinth:20190116150044p:plain

今度はPull requestsメニューからNew pull requestボタンを押して、プルリクエストを作成します。
f:id:mistyrinth:20190116150232p:plain

base: masterのままcompare: add-sort-func2を選択すると、自動マージができないと言われました🤨
競合が発生しているからですね〜!
そのままConfirm pull requestを行い、プルリクエストの作成を実行すると、コンフリクトがあると言われます。
f:id:mistyrinth:20190116150652p:plain

InsightsNetworkから、ブランチの様子を見ることができます。
f:id:mistyrinth:20190116150828p:plain

3-2. 競合の解決

この競合を解決するには、Resolve conflictsボタンを押します🙂すると競合箇所が表示されます!!
f:id:mistyrinth:20190116151238p:plain

今回の場合は厳密等価演算子===を使用するように競合を解決して、Commit mergeボタンを押します。
f:id:mistyrinth:20190116151556p:plain

あとは通常通りにマージしていき、完了です👏✨
f:id:mistyrinth:20190116151722p:plain

f:id:mistyrinth:20190116151731p:plain

以上です〜!