おさらい
前回【第3回】 Git/Githubを使ってコードを管理しようでは、GitとGithubを実際に使ってみました。
Gitの基本的な流れ
Gitを使う上での基本的な流れをおさらいしておきましょう。
Gitはローカルでファイルの変更履歴を管理する仕組み・ツールです。
まずはローカルにリポジトリを作成します。
リポジトリとは、Gitで管理するファイルやディレクトリのことを指します。
git init
コマンドを実行することで、そのディレクトリをリポジトリとして扱うことができます。
- ファイルを変更する
- 変更をステージにAddする
git add <file>
- 変更をCommitする
git commit -m "<message>"
これを繰り返すことで、変更履歴を管理することができます。
いまどの状態かを確認するには、git status
を実行します。
過去の変更履歴を確認するには、git log
を実行します。
Githubの基本的な流れ
Githubを使う上での基本的な流れをおさらいしておきましょう。
GithubはリモートでGitログのクラウド管理を行い、さらに不特定多数の人との共同開発をマネジメントする仕組み・ツール・サイトです。
- Github上でリポジトリを作成する
- Gitのローカルリポジトリにリモートリポジトリを登録する
git remote add origin <url>
- ローカルリポジトリの変更をリモートリポジトリにPushする
git push origin <branch>
これを繰り返すことで、リモートリポジトリに変更履歴をどんどん追加していくことができます。
使うコマンドまとめ
用語 | 役割 | コマンド | 例 |
---|---|---|---|
初期化 | リポジトリを作成する | git init | git init |
アド(ステージ) | 変更をステージに追加する | git add <file> | git add index.html |
コミット | 変更をリポジトリに追加する | git commit -m "<message>" | git commit -m "add index.html" |
プッシュ | 変更をリモートリポジトリに追加する | git push origin <branch> | git push origin master |
ステータス | 現在の状態を確認する | git status | git status |
ログ | 過去の変更履歴を確認する | git log | git log |
リモート | リモートリポジトリを登録する | git remote add origin <url> | git remote add origin |
Gitでの共同開発に必要な知識
ブランチ
ブランチとは、リポジトリの変更履歴を分岐させることができる機能です。 歴史や樹形図のようなものをイメージするとわかりやすいです。
コミットを一まとまりとして扱うことができ、共同開発においてこのブランチが機能開発の単位となります。
ブランチを作成するには、git branch <branch>
を実行します。
ブランチを切り替えるには、git checkout <branch>
を実行します。
発展
git checkout
コマンドは、ブランチの切り替え以外にも、コミットの切り替えや、ファイルの復元などにも使うことができます。
過去のコミットへ一時的に戻りたいときは、git checkout <commitのハッシュ>
を実行します。
(あたらにgit switch
コマンドが追加されまして、こちらも利用できます。)
また、便利コマンドとして、git checkout -b <branch>
があります。
これは、git branch <branch>
とgit checkout <branch>
を同時に実行するコマンドです。
ブランチを作成して、そのブランチに切り替えるという作業を一度に行うことができます。
マージ
マージとは、ブランチを統合することです。 ブランチを作成して機能を開発し、その機能が完成したらマージして統合します。
マージをするには、git merge <branch>
を実行します。
マージすると、マージ元のブランチにマージ先のブランチの変更履歴が追加されます。
コンフリクト
コンフリクトとは、マージするときに起こる衝突のことです。 もちろん複数人や複数の歴史で同じ場所を変更すると衝突が起きますよね?
コンフリクトが起きたときは、git status
でコンフリクトの場所を確認することができます。
やってみよう
前回【第3回】 Git/Githubを使ってコードを管理しようで作成したリポジトリを使います。
Gitではinitした時点でmain
というブランチが一番大元のブランチとして作成されます。
ブランチを作成する
まずは、ブランチを作成してみましょう。
git branch <branch>
を実行することで、ブランチを作成することができます。
git branch add-function
ブランチを切り替える
次に、ブランチを切り替えてみましょう。
git checkout <branch>
を実行することで、ブランチを切り替えることができます。
git checkout add-function
いまどのブランチにいるかを確認するには、git branch
を実行します。
git branch
* add-function
main
*
がついているブランチが現在のブランチです。
ファイルを変更する
ブランチを切り替えたら、ファイルを変更してみましょう。
ブランチ名のとおり、今回はadd
という関数を変更として追加してみます。
#include <bits/stdc++.h>
using namespace std;
int add(int a, int b) {
return a + b;
}
int main() {
cout << add(3, -2) << endl;
return 0;
}
変更をステージにAddする
ファイルを変更したら、変更をステージにAddしてみましょう。
git add main.cpp
変更をCommitする
ファイルを変更したら、変更をステージにAddしてみましょう。
git commit -m "足し算の関数を追加"
これで、変更履歴がリポジトリに追加されました。
確認してみよう
git log
を実行して、変更履歴を確認してみましょう。
git log
commit <commitのハッシュ> (HEAD -> add-function)
Author: <username> <email>
Date: <date>
足し算の関数を追加
commit <commitのハッシュ> (origin/main, origin/HEAD, main)
Author: <username> <email>
Date: <date>
Hello WorldをHello Maximumに修正
commit <commitのハッシュ>
Author: <username> <email>
Date: <date>
Hello Worldと表示するプログラムを作成
HEAD
がついているのが現在のブランチです。
main
ではなくadd-function
になっていることがわかります。
視覚的に見る
VSCodeの拡張機能であるGit Graphを使うと、視覚的に変更履歴を確認することができます。 これを使って、変更履歴を確認してみましょう。
はい、こんな感じで枝分かれした先に変更履歴が追加されていることがわかります。
では、main
ブランチに戻ってみましょう。
git checkout main
ローカルでマージする
main
ブランチに戻ったら、add-function
ブランチをmain
ブランチにマージしてみましょう。
git merge add-function
はい、これでadd-function
ブランチの変更履歴がmain
ブランチに追加されました。
リモートリポジトリにPushする
ローカルでマージしたら、リモートリポジトリにPushしてみましょう。
git push origin main
これで、リモートリポジトリにも変更履歴が追加されました。
Githubでの共同開発に必要な知識
Githubを使うことで、複数人で同じプログラムを開発することができます。 さらにMaximumなど、組織を作って管理権限を付与したり、プロジェクトをまとめて管理したりすることもできます。
Githubでの共同開発に必要な知識を学びましょう。
Issue
Issueとは、Github上でタスク管理を行う機能です。
Issueを作成することで、タスクを登録することができます。 Issue Flowという開発体制があり、一般にはこのフローで開発することが多いため、こちらをベースに説明していきます。
Pull Request
先ほどブランチをローカル環境でMergeしましたが、共同開発たるもの、全て自分がMergeの権限を持つわけではありません。 そこでGithub上で「自分のコードよかったらMergeしてください」というリクエストを出すことができます。
これをPUll Requestと言います。
レビュー
コードがいいかどうかチェックする工程(主にGithub上でのこと)をレビューと言います。基本はテックリードやCTOに当たるポジションのエンジニアが、部下の開発したコードが動くか、正しく欠けているかをチェックします。
リモートでのマージ
リモートでもローカルと同じようにMergeができます。MergeができるタイミングはPull Requestを承諾した時です。
実際にやってみましょう
これ以降説明を簡単にするために、登場人物を設定します。
あなたがAさんで、共同開発者役をBさんが担当するとします。 ここでAさんが監督、Bさんが作業者とします。
Aさんを作成する
Issueを作成してみます。
今回は先ほど作った足し算の関数の引数が負の数だったときに、エラーを返すように修正するタスクをするとします。
「Issue」タブをクリックして、New Issueをクリックします。
タイトルに「負の数の足し算を規制する」と入力し、Assignerにそのタスクを担当する人を選択します。
この画像の赤い枠で囲ったところです。 誰か共同開発者役のペアを作って、その人が担当するとわかりやすいです。 もし共同開発者の方の名前を入力しても出てこない場合は、SettingsタブのCollaboratorsから招待してください。
AさんがIssueを作成したら、作業者であるBさんにIssueをAssignします。
Bさん:作業リポジトリをCloneする
もし、作業対象のリポジトリが作業者のローカル環境にない場合は、リモートリポジトリをCloneします。 もしすでにローカルにリポジトリがある場合はこの作業は不要です。
git clone <url>
このとき、リモートリポジトリのURLは、Github上のCodeタブのリポジトリの右上にある緑色Codeボタンからコピーできます。
Bさんはその組織に入ったばかりで、ローカルにリポジトリがないので、リモートリポジトリをCloneしてきます。
Bさん:ブランチを作成する
Issueを作成したら、作業者であるBさんがブランチを作成します。 ローカルでもGithub上でもどちらでもブランチを作成できますが、Issue Flow形式で進めたいので、Github上でブランチを作成します。
Issue画面の右下にCreate a Branch
というボタンがあるので、クリックしてブランチを作成します。
この画像の黄色い枠で囲ったところです。
ブランチ名は英語で、もっと言うとkebab-case
で書くのが一般的です。
今回はvalidate-negative-number
というブランチ名にします。
そうすると、このコマンドを実行してねと言わんばかりのコマンドが出てきます。
git fetch origin
git checkout <設定したブランチ名>
これをコピーして、ローカルで実行します。
git branch
と実行してブランチが作成されていることと、そのブランチにいることを確認します。
BさんはAさんにこのIssueをAssignされたので、その機能を開発するためのブランチを作成します。
Bさん:機能を開発する
ブランチを作成したら、機能を開発します。 今回は、足し算の関数の引数が負の数だったときに、エラーを返すように修正するタスクをするとしました。
#include <bits/stdc++.h>
using namespace std;
int add(int a, int b) {
if (a < 0 || b < 0) {
return exit(1);
}
return a + b;
}
int main() {
cout << add(3, -2) << endl;
return 0;
}
これをローカルでコミットします。
git add main.cpp
git commit -m "負の数の足し算を規制"
BさんはAssignされたIssueの内容に従って、ローカルで機能を開発します。
Bさん:リモートリポジトリにPushする
機能を開発したら、リモートリポジトリにPushします。
git push origin <今いるブランチ名>
Bさんは機能を開発し終えたので、リモートリポジトリにPushします。
Bさん Requestを作成する
リモートリポジトリにPushしたら、Pull Requestを作成します。 共同開発では直接mainへ開発した機能をマージするのではなく、基本的にはPull Requestを作成して、監督者のレビューを受けてからマージします。 自分が開発したコードに「バグがないか」「コードが汚くないか」「セキュリティ上問題ないか」などをチェックしてもらうためです。
Pull Requestを作成するには、Github上でCompare & pull request
をクリックします。
もし出てこない場合はPull RequestタブからNew pull request
をクリックして、マージ先をmain
、マージ元を今pushしたブランチに設定してください。
そしたら、Pull Requestのタイトルと本文をレビューする側の人がわかりやすいように書きます。
Reviewersにレビューする人を設定します。 レビューする人は複数人設定することができます。
Bさんは機能を開発し終えたので、Pull Requestを作成します。 ReviewersにAさんを設定します。
なぜ本文やタイトル、Commit Messageを細かく書くのか
レビューをする時は基本、Pull Requestの本文とコミットメッセージを見て大まかな内容や開発の流れを把握します。
みなさんも他人の書いたコードを読む時、読むのにとても時間がかかると思います。
それと同じで、レビューをする人はPull Requestの本文やコミットメッセージを読むのに時間がかかります。
このレビュワーの負担をできるだけ軽減できる工夫がPull Requestの本文やタイトル、コミットメッセージを細かく書く
ということです。
Aさん Requestをレビューする
Pull Requestを作成したら、レビューをします。
レビューをするには、Pull Requestの画面のFiles changedタブをクリックします。 そうすると、Pull Requestに含まれる変更履歴が表示されます。 ここでは変更履歴を確認して、問題がないかをチェックします。
今回の例ではexit(1)
という関数を使っているので、これは問題ありです。
exit(1)
はプログラムを強制終了させる関数なので、これを使うとプログラムが強制終了してしまいます。
レビューコメントは行単位でつけることができますので、今回私はこのようにexit(1)
の行にレビューコメントをつけました。
全てのレビューを終えたら、Review changesをクリックして、レビューを完了します。
このとき、もしレビューに問題がある場合はRequest changesをクリックし、逆に問題がない場合はApproveをクリックします。
AさんはBさんが作成したPull Requestをレビューします。 今回は
exit(1)
を使っているので、コードに問題があると判断しました。 そのため、Request changesをクリックして、Bさんに修正を依頼します。exit(0)
を使うように修正してもらいましょう。
Bさん:再び機能を開発する
レビューを受けたら、Pull Requestを作成したブランチに戻って、機能を修正します。
#include <bits/stdc++.h>
using namespace std;
int add(int a, int b) {
if (a < 0 || b < 0) {
return exit(0);
}
return a + b;
}
int main() {
cout << add(3, -2) << endl;
return 0;
}
また、AddしてCommitしてPushします。(省略)
Pushすると、Pull Requestに修正が反映されます。 そのため、再度レビューをしてもらうように依頼します。 Reviewers部分のRe-request reviewをクリックすると、レビューを再度依頼することができます。
BさんはAさんからレビューを受けたので、Pull Requestを作成したブランチに戻って、機能を修正します。 今回は
exit(1)
をexit(0)
に修正しました。 その後、AddしてCommitしてPushします。 これで、Pull Requestに修正が反映されました。 Reviewers部分のRe-request reviewをクリックして、再度レビューを依頼します。
Aさん:再びPull Requestをレビューする
さあ、再修正されたPull Requestをレビューしましょう。
(省略)
今度は問題ないので、Approveをクリックします。
AさんはBさんから再度レビューを依頼されたので、Pull Requestを再度レビューします。 今回は
exit(1)
をexit(0)
に修正してもらったので、問題ないと判断しました。 そのため、Approveをクリックして、Pull Requestを承認します。
Aさん:マージする
Pull Requestを承認したら、マージします。 Pull Requestをマージするのは基本CTOやテックリードなどの監督の人が行います。
Pull Requestの画面のMerge pull requestをクリックします。
AさんはPull Requestを承認したので、Pull Requestをマージします。 Pull Requestの画面のMerge pull requestをクリックして、Pull Requestをマージします。 これで、Pull Requestに含まれる変更履歴が
main
ブランチに追加されました。
マージされると、今までOpenだったPull RequestがMergedになります。 さらに、Issueからブランチを作成したため、IssueもClosedになります。 これでIssue Flowにおける一つの機能開発の単位が完了しました。
まとめ
これを図にすると、以下のようになります。