【第4回】Git(GitHub)入門

コードを管理したり共同開発をするためのGit(GitHub)の使い方を解説します。

Homeブログ一覧【第4回】Git(GitHub)入門

Gitとは

Gitはプログラムのソースコードやファイルの変更履歴を管理するための分散型バージョン管理システムです。

Gitのインストール

入会届でGitHubアカウントを作成し、入会まで完了された方はこちらに進んでください。

本サークルでは、LinuxにGitをインストールする手順を説明します。WindowsやMacの場合は、公式サイトからインストーラをダウンロードしてください。

また、弊学ではWSLを開発環境として使うことが多いため、Windows側ではなくWSL側(Linux)にGitを入れることをお勧めします。

Ubuntuの場合

ターミナルを開き、以下のコマンドを実行してください。

sudo apt install git

インストール後にバージョンを確認するために、以下のコマンドを実行してください。

git --version

Gitの初期設定

Gitをインストールしたら、初期設定を行います。ターミナルを開き、以下のコマンドを実行してください。

git config --global user.name "<username>"
git config --global user.email "<email>"

<username><email>にはGitHubアカウントで登録したユーザ名とメールアドレスを入力してください。 設定した情報の確認は、以下のコマンドを実行してください。

git config --global --list
GitHub CLIの認証

レポジトリやIssueなどの操作には、GitHub CLIなどを使ってSSH認証を行う必要があります。

以下のコマンドを実行してください。

(type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
&& sudo mkdir -p -m 755 /etc/apt/keyrings \
&& wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& sudo apt update \
&& sudo apt install gh -y

詳しくはこちらを参照してください。

ソースコードを管理してみよう

リポジトリを初期化する

まず、git-introという作業用ディレクトリを作成します。

次に、VSCodeではデフォルトで特定のフォルダを表示しない設定がされているので、表示するように設定を変更します。 ファイル > ユーザー設定 > 設定 > Files Excludeにおいて、**/.gitを削除してください。

また、VSCodeの自動保存機能を有効にしておきましょう。「ファイル」から「自動保存」にチェックを入れてください。

Gitリポジトリを初期化します。git-introディレクトリ内でターミナルを開き、以下のコマンドを実行してください。

git init

これで、.gitというディレクトリが作成され、このディレクトリがGitの管理対象となりました。

リポジトリとは、Gitで管理するファイルやディレクトリのことを指します。

コミットしてみよう

git-introディレクトリ内にmain.cppというファイルを作成し、以下のコードを記述してください。

main.cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
    cout << "Hello, World" << endl;
    return 0;
}

新しく作成したmain.cppUntracked(未追跡) 状態であり、まだGitの管理下にないことを示しています。 これはコマンドでも確認できます。以下のコマンドを実行してください。

git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        main.cpp

nothing added to commit but untracked files present (use "git add" to track)

では、このmain.cppファイルをGitの管理下に置いてみましょう。以下のコマンドを実行してください。

git add main.cpp

main.cppファイルが Added(追加) 状態になりました。これは、Gitの管理下に置く準備ができたことを示し、これを ステージング と言います。 これはコマンドでも確認できます。以下のコマンドを実行してください。

git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   main.cpp

Untracked filesだったファイルがChanges to be committedに変わっていることが確認できます。

それでは、このファイルをGitの管理対象に追加しましょう。以下のコマンドを実行してください。

git commit -m "Hello, Worldを表示するプログラムを追加"
[master (root-commit) xxxxxxx] Hello, Worldを表示するプログラムを追加
 1 file changed, 7 insertions(+)
 create mode xxxxxx main.cpp

-mオプションは、コミットメッセージを指定するためのオプションです。コミットメッセージは、そのコミットに対する説明を記述するために使います。

これで、main.cppファイルがGitの管理下に置かれ、コミットされました。

修正をコミットしてみよう

Hello, WorldHello, Maximumに変更してみましょう。 main.cppファイルを修正し、以下のコードに変更してください。

main.cpp
#include <bits/stdc++.h>
using namespace std;

int main(){
-    cout << "Hello, World" << endl;
+    cout << "Hello, Maximum" << endl;
    return 0;
}

ファイルに変更があったため、Modified(変更済み) 状態になります。以下のコマンドを実行してください。

git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   main.cpp

no changes added to commit (use "git add" and/or "git commit -a")

修正したmain.cppファイルの変更をコミットします。以下のコマンドを実行して、確認してください。

git add main.cpp
git commit -m "Hello, WorldからHello, Maximumに変更"
[master xxxxxxx] Hello, WorldからHello, Maximumに変更
 1 file changed, 1 insertion(+), 1 deletion(-)

これで、main.cppファイルの変更がGitの管理下に置かれ、コミットされました。

VSCodeでのGitにおけるファイルの状態には、以下のようなものがあります。

アルファベット状態意味
UUntrackedgitが未追跡、新規作成
MModified変更済み
AAdded新規追加
CConflict競合
DDeleted削除
RRenamed名前変更
SSubmoduleサブモジュール

コミット履歴を確認してみよう

コミット履歴を確認するには、以下のコマンドを実行してください。

git log
commit xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (HEAD -> master)
Author: batora9 <[email protected]>
Date:   Sun May 19 19:10:29 2024 +0900

    Hello, WorldからHello, Maximumに変更

commit xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Author: batora9 <[email protected]>
Date:   Sun May 19 19:07:17 2024 +0900

    Hello, Worldを表示するプログラムを追加

これで、コミット履歴が表示されます。

Gitの基本的な流れ

Gitの基本的な流れをおさらいしましょう。

Gitはローカルでファイルの変更履歴を管理することができるツールです。

  1. リポジトリを初期化する

    git initでリポジトリを初期化します。

  2. ファイルを変更する

    ひと通りの作業をする

  3. 変更をステージングする

    git add <ファイル名>でファイルの変更をステージングします。

  4. ファイルをコミットする

    git commit -m "<コミットメッセージ>"でファイルをコミットします。

1~3を繰り返すことで、ファイルの変更履歴を管理することができます。

現在のリポジトリの状態を確認するには、git statusを実行し、過去の変更履歴を確認するには、git logを実行してください。

Web研では今後の講習ではGitを使って実際に書いたコードを保存しておけるようにしていきます。

GitHubとは

GitHubは、Gitリポジトリをリモートで管理するためのサービスです。リモートで管理することで、Gitのログをクラウド上で管理することができたり、他のユーザーとの共同開発をマネジメントすることができます。

リモートリポジトリを作成してみよう

GitHubにログインし、マイページ上部の「Repository」をクリックし、緑色の「New」ボタンをクリックしてください。

GitHubリポジトリ作成

Repository nameにgithub-introと入力し、Create Repositoryボタンをクリックしてください。(その他の設定はデフォルトのままで大丈夫です)

作成したリポジトリのURLをコピーしておいてください。

VSCodeに戻って、以下のコマンドを実行してください。

git remote add origin <リポジトリURL>.git

<リポジトリURL>には、先ほどコピーしたリポジトリのURLを入力してください。

リモートリポジトリにプッシュしてみよう

リモートリポジトリを登録したので、ローカルでの開発内容をリモートリポジトリに送信します。

リモートリポジトリにプッシュするには、以下のコマンドを実行してください。

git branch -M main # ブランチ名をmainにする
git push -u origin main # リモートリポジトリにmainブランチをプッシュする

自分のGitHubのリポジトリにアクセスして、リモートリポジトリに送信されていることを確認してください。

GitHubでの共同開発に必要な知識

前述したように、GitHubを使うことで他のユーザーと複数人での共同開発が可能になります。さらに、Maximumなどの組織を作って、管理権限を設定したり、プロジェクトをまとめて管理することもできます。

Issue

Issueは、プロジェクトの進捗状況やバグの報告、機能の提案などを管理するための機能です。Issueを使うことで、プロジェクトの進捗状況を把握しやすくなります。

Pull Request

先ほどブランチをローカル環境でMergeしましたが、共同開発においては全て自分がMergeをする権限を持つわけではありません。 Pull Requestは、自分のブランチの変更を特定のブランチに統合するためのリクエストです。Pull Requestを使うことで、他のメンバーに変更をレビューしてもらったり、コードの品質を保つことができます。

Review

Pull Requestを送信した際に、他のメンバーに自分の書いたコードをレビューしてもらうことができます。レビューを任された人は、変更を確認してコメントを残したり、Approve(承認)やRequest changes(変更の要求)をすることができます。

Merge

リモートでもローカルと同じようにMergeを行うことができます。共同開発では、Branch Protectionという機能を使うことでPull RequestがApproveされないとMergeできないように設定することができます。(これは、レビューをする前にMergeされることを防ぐためです)

Conflict

複数のユーザーが同じファイルを変更し、それをリモートリポジトリにプッシュしようとすると(厳密には、自分がブランチを切った後かつ自分がPRを出す(マージをする)前に誰かが同じところに変更を入れたとき)、競合(Conflict)が発生します。競合が発生した場合は、競合を解消するために手動でファイルを修正する必要があります。

ブランチを作成してみよう

ブランチは、リポジトリ内での作業を分岐させるための機能です。ブランチを使うことで、複数の作業を同時に進めることができます。

ブランチを作成して切り替える

新しいブランチを作成してmain.cppに足し算を行うプログラムを追加してみましょう。

まず、新しいブランチを作成します。以下のコマンドを実行してください。

git branch add-func

次に、作成したブランチに切り替えます。以下のコマンドを実行してください。

git checkout add-func
同時にブランチを作成して切り替える方法
git checkout -b add-func

このコマンドを実行すると、新しいブランチが作成され同時にそのブランチに切り替わります。

add-funcという名前のブランチが作成され、そのブランチに切り替わります。

今どのブランチにいるか確認するために、以下のコマンドを実行してください。

git branch
* add-func
  main

*が付いているブランチが現在のブランチです。

main.cppの中身を変更します。

main.cpp
#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;
}

変更をコミットしてみよう

main.cppの変更をステージングし、コミットします。

git add main.cpp
git commit -m "足し算を行う関数を追加"

git logを実行して、コミット履歴を確認してみましょう。

git log
commit xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (HEAD -> add-func)
Author: batora9 <xxx.example.com>
Date:   Mon May 20 00:22:47 2024 +0900

    足し算の関数を追加

commit xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (origin/main, main)
Author: batora9 <xxx.example.com>
Date:   Sun May 19 19:59:01 2024 +0900

    Hello, WorldからHello, Maximumに変更

commit xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Author: batora9 <xxx.example.com>
Date:   Sun May 19 19:58:30 2024 +0900

    Hello, Worldを表示するプログラムを追加

HEADが付いているのが現在のブランチです。mainではなくadd-funcになっていることが確認できます。

ブランチをマージしてみよう

add-funcブランチでの作業が完了したので、mainブランチにマージします。

まず、mainブランチに切り替えます。

git checkout main

次に、add-funcブランチをmainブランチにマージします。

git merge add-func

リモートリポジトリにプッシュしてみよう

mainブランチに変更をマージしたので、リモートリポジトリにプッシュします。

git push origin main

これで、リモートリポジトリにも変更が反映されました。

共同開発をしてみよう

ちょっとした共同開発をやってみましょう。2人でペアを組んでAさん、Bさんとします。

Issueを作成(A)

Aさんは、先ほど作成したレポジトリの「Issue」にアクセスし、「New issue」ボタンをクリックします。

Issue作成

タイトルと説明を入力しましょう。

右のAssigneesで、Issueを担当する人を選択することができます。 今回はBさんが担当するので、Bさんを選択してください。

Collaboratorsの招待方法

BさんのGitHubのユーザーネームを入力してもでてきません。「Settings」の「Collaborators」よりBさんを追加し、招待してください。

招待方法

Bさんに招待メールが送信されます。

Collaboratorsの招待メール

Issue作成フォーム

Issueのリストに作成したIssueが表示されます。

Issue作成完了

ブランチを作成(B)

まず、BさんはAさんのリポジトリをクローンします。(もし、作業対象のリポジトリがローカルに存在する場合はこの作業は不要です)

git clone <AさんのリポジトリURL>.git

Bさんはその組織に入ったばかりで、ローカルにリポジトリがないので、リモートリポジトリをCloneしてきます。

BさんはAさんの作成したIssueにアクセスし、ブランチを作成します。

ブランチ作成

ブランチ名を入力し、「Create branch」ボタンをクリックしてください。

機能を開発する(B)

Bさんは、main.cppに引き算を行う関数をを追加します。

まずは、クローンしたリポジトリのディレクトリに移動しブランチを切り替えます。

git fetch origin
git checkout subtract-func

ここでのsubtract-funcは、先ほど設定したブランチ名です。

main.cppの中身を変更します。

main.cpp
#include <bits/stdc++.h>
using namespace std;

int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a * b;
}

int main() {
    cout << add(3, -2) << endl;
    cout << subtract(3, -2) << endl;
    return 0;
}

subtract関数の中身が*(掛け算)になっていますがそのままにしておきます。

変更がある程度または完了したら、ローカルでコミットします。

git add main.cpp
git commit -m "引き算の関数を追加"

リモートリポジトリへプッシュする(B)

すべての変更が完了したら、リモートリポジトリにPushします。

git push origin subtract-func

Pull Requestを作成(B)

リモートリポジトリにPushをしたら、Pull Requestを作成します。共同開発では直接mainへ開発した機能をマージするのではなく、基本的にはPull Requestを作成して、監督者のレビューを受けてからMergeします。 自分が開発したコードに「バグがないか」「コードが汚くないか」「セキュリティ上問題ないか」などをチェックしてもらうためです。

Pull Requestを作成するには、リポジトリのページにアクセスし、「Compare & pull request」ボタンをクリックしてください。もしくは、リポジトリのページにアクセスし、「Pull requests」タブをクリックし、「New pull request」ボタンをクリックしてください。

Bさんは機能を開発し終えたのでPull Requestを作成します。 ReviewersにAさんを設定します。

なぜ本文やタイトル、Commit Messageを分かりやすく簡潔に書くのか

レビューをする時は基本、Pull Requestの本文とコミットメッセージを見て大まかな内容や開発の流れを把握します。 みなさんも他人の書いたコードを読む時、読むのにとても時間がかかると思います。 それと同じで、レビューをする人はPull Requestの本文やコミットメッセージを読むのに時間がかかります。 このレビュワーの負担をできるだけ軽減できる工夫がPull Requestの本文やタイトル、コミットメッセージをわかりやすく簡潔に書くということです。

レビューをする(A)

Aさんは、Bさんが編集したコードをレビューします。

Review

レビューは1行ずつコメントを残すことができます。コメントを残すことでコードの問題点を指摘したり、改善点を提案することができます。

また、問題のある場合にはRequest changesとして、修正を要求することもできます。

今回、引き算の関数ではなく掛け算の関数を追加してしまったため、AさんはBさんに修正を要求します。

Review changes」からBさんへのコメントを残し、「Request changes」にチェックを入れ、「Submit review」をクリックしてください。

修正を行う(B)

BさんはAさんのコメントを受けて、修正を行います。

main.cpp
#include <bits/stdc++.h>
using namespace std;

int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;
}

int main() {
    cout << add(3, -2) << endl;
    cout << subtract(3, -2) << endl;
    return 0;
}

修正が完了したら、再度コミットしてプッシュします。

git add main.cpp
git commit -m "引き算の関数に修正"
git push origin subtract-func

プッシュをすると、リモートに修正が反映されます。

再度レビューをお願いするためには、Reviewersのところの「Re-request review」をクリックします。

Re-request review

再度レビューをする(A)

Bさんが修正を行ったので、Aさんは再度レビューを行います。

変更が正しければ、「Approve」にチェックを入れ、「Submit review」をクリックしてください。

マージする(A)

Aさんがレビューを承認したので、Bさんのブランチをマージします。

マージするには、「Merge pull request」をクリックしてください。

Merge

マージが完了すると、Bさんのブランチの変更がmainブランチに統合され、反映されます。

マージされると、今までOpenだったPull RequestがMergedになります。 さらに、Issueからブランチを作成したため、IssueもClosedになります。

これで、ひと通りの共同開発による開発フローが完了しました。

ローカルリポジトリを更新する(A)

最後に、Aさんはリモートリポジトリの変更をローカルリポジトリに反映させます。

git pull origin main

これで、Aさんのローカルリポジトリも最新の状態になりました。

視覚的に変更を見る

VSCodeの拡張機能であるGit Graphを使うと、リポジトリの変更履歴を視覚的に確認することができます。

先ほどの共同開発の流れをGit Graphで確認してみましょう。

Git Graph

public-websiteでのGit Graph: Git Graph

最低限覚えて欲しいこと

  • Git -> 書いたコードを途中でセーブしてやり直したりできるやつ。

  • GitHub -> Gitで管理してるコードを無料でアップロードしたり共同開発をサポートしてくれるクラウド。

  • Add -> コードに対する変更をコミットする対象に含める行為、git add

  • Commit -> Addされたものをセーブする行為、git commit

  • Push -> CommitされたものをGitHubなどのリモートリポジトリに反映させる行為、git push

よく使うコマンドまとめ

コマンド説明
git initリポジトリを初期化するgit init
git add <ファイル名>ファイルをステージングするgit add index.html
git commit -m "<コミットメッセージ>"変更をコミットするgit commit -m "index.htmlを追加"
git statusリポジトリの状態を確認するgit status
git logコミット履歴を確認するgit log
git remote add origin <リポジトリURL>リモートリポジトリを追加する
git push -u origin <ブランチ名>上流ブランチとして設定するgit push -u origin main
git push origin <ブランチ名>リモートリポジトリにプッシュするgit push origin subtract-func
git branchブランチを確認するgit branch
git branch <ブランチ名>ブランチを作成するgit branch add-func
git checkout <ブランチ名>ブランチを切り替えるgit checkout main
git checkout -b <ブランチ名>ブランチを作成して切り替えるgit checkout -b add-func
git merge <ブランチ名>ブランチをマージするgit merge add-func
git clone <リポジトリURL>リポジトリをクローンする
git fetch originリモートリポジトリの情報を取得する
git pull origin <ブランチ名>リモートリポジトリからプルするgit pull origin main

Gitのコマンドは使っていくうちに覚えていくので、まずは自分からこれまでのコードを管理してみたり、なにかアプリを作ってコードを管理してみるところから始めてみましょう。