【実践】Gitの基礎概念からGitHubで共同開発ができるまで

興味本位でGitの使い方を学んだので、手順を整理してみます。

この記事のゴール

この記事では、下図の構成が理解できるようになるのと、実際にバージョン管理ができるようになることがゴールとなります。

環境

今回はAWSのAmazon Linux 2を使いますが、Gitが使える環境なら何でも良いと思います。

Git(座学)

Gitとは

Gitとは、分散型バージョン管理システムです。

誤解を恐れずに言うと、どれを編集したのか、いつ編集したのか、誰が編集したのか、などといった変更履歴を管理してくれるシステムです。

なぜGitを使うのか

結論から書きます。

  • 共同作業を効率よく進めるため
  • 共有ファイルを編集する際の不整合を減らすため
  • バックアップをとる手間が省けるため

通常の場合、共有ファイルを複数人で編集する時は下図のようになります。

これだと、「誰かが編集している間は同じファイルを編集できない」や「同じファイルに対して、複数のプロジェクトが並列に取り扱ってしまった(競合と呼ぶ)」などといった不整合が発生することがあります。

Gitの場合は、下図のように、ユーザー毎にコピーフォルダを作り、そのフォルダに対して作業を行います。

そうすると、前述のような不整合は発生しづらくなります。

これを見ると、Gitが分散型バージョン管理システムと呼ばれる理由が分かると思います。

また、何らかのファイルを編集する前に、念の為バックアップをとることがあるかと思いますが、Gitを使うとそのようなバックアップ作業も不要となります。

Gitの基礎概念

次はGitの基礎概念について箇条書きします。

  • ワークツリー (作業中のフォルダ)
  • インデックス(修正内容を反映させたいファイル)
  • ローカルリポジトリ(コピーフォルダ)
  • リモートリポジトリ(共有フォルダ)

カッコの中は、先程の例に対応させています。

特によく使われる言葉を箇条書きします。

  • コミット(インデックス → ローカルリポジトリ)
  • プッシュ(ローカルリポジトリ → リモートリポジトリ)
  • プル(リモートリポジトリ → ローカルリポジトリ)
  • クローン(リモートリポジトリからローカルリポジトリを生成する)

また、より詳細に書くと、下図のようになるそうです。

Git(実践)

実践に移りますが、まずは、ローカルリポジトリだけを扱います(リモートリポジトリはこの後のGitHubで実践します)。

ローカルリポジトリ作成

Gitをインストールし、myweb1という作業場をつくり、ローカルリポジトリを作ります。

# Gitインストール
$ yum install -y git

# 任意の場所にmyweb1を作成
$ mkdir ~/myweb1

# myweb1に移動
$ cd ~/myweb1

# 新規リポジトリを作成(.gitというディレクトリが作成される)
$ git init

変更履歴を管理する

次に、index.htmlというファイルを作ります。

# ファイルを作成し、version1という文章を追加する
$ vi index.html

version1

ここで、次のコマンドを叩いてみます。

$ git status

On branch master

#「まだコミットされていない」と言われてます
No commits yet 

#未追跡(インデックスされていない)のファイルがあるので、
#git addコマンドを使ってインデックスしろと言われています
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	index.html 

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

index.htmlがインデックスされていないので、「git add ファイル名」コマンドでインデックスしなさい、と言われているので、素直に従います。

# index.htmlをインデックスする
$ git add index.html

# ステータス確認
$ git status

On branch master

#「まだコミットされていない」と言われてます
No commits yet

# コミットする予定のファイルが表示されます
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
	new file:   index.html

これでコミットの準備が出来たので、コミットしてみます。

# コミット
$ git commit -m "Version1を作成"

[master (root-commit) d57ddf3] Version1を作成
 1 file changed, 1 insertion(+)
 create mode 100644 index.html

無事にコミット出来ました。ついでにコミットの履歴を確認してみます。

# コミットの履歴を確認
$ git log

commit d57ddf35ab628b1c5d6d78e2c035305e35d8d3c0 (HEAD -> master)
Author: hoge <hoge@hoge.com>
Date:   Sun Sep 12 13:25:56 2021 +0900

    Version1を作成

ちゃんとコミットできています。

同様に、Version2を作成していきます。

# index.htmlを編集
$ vi index.html

version1
version2 #ここを追加
# インデックス
$ git add index.html

# コミット
$ git commit -m "Version2を作成"

# コミット履歴を確認
$ git log

commit 77cc7387296e34467839ef69e43ac98ffa8498f7 (HEAD -> master)
Author: hoge <hoge@hoge.com>
Date:   Sun Sep 12 13:31:22 2021 +0900

    Version2を追加

commit d57ddf35ab628b1c5d6d78e2c035305e35d8d3c0
Author: hoge <hoge@hoge.com>
Date:   Sun Sep 12 13:25:56 2021 +0900

    Version1を作成

「やっぱりVersion2いらねー!」となったときは、次のようにします。

# 戻りたいコミットのハッシュ値を指定(git logで確認できる)
$ git reset --hard d57ddf35ab628b1c5d6d78e2c035305e35d8d3c0

# index.htmlがversion1の状態に戻っている
$ vi index.html

version1

「やっぱVersion2いるー!」となったときは、次のようにします。

# コミットやリセットの履歴を確認(10個まで表示させる)
$ git reflog -n 10

77cc738 (HEAD -> master) HEAD@{8}: commit: Version2を追加
d57ddf3 HEAD@{9}: commit (initial): Version1を作成

# Version2まで戻す(ハッシュ値は上を参照)
$ git reset --hard 77cc738

# index.htmlがVersion2に戻っていることを確認
$ vi index.html

version1
version2

ブランチを切る

ここまでは、Version1とVersion2をひとつずつ順番にコミットしました。

では、Version2とVersion3を同時進行で行いたい場合どうすればよいか。

そこで、ブランチというものが登場します。

ブランチを切れば、Version2とVersion3を独立させて、同時進行で作業することが可能になります。

では、ver3ブランチで作業をした後に、masterブランチに合流(マージ)してみます。

# ブランチ確認
$ git branch
* master

# ver3ブランチを切る
$ git branch ver3

# ブランチ確認
$ git branch
* master
  ver3

# ver3ブランチへ移動
$ git checkout ver3

# ブランチ確認
$ git branch
  master
* ver3

では、ver3ブランチでindex.htmlを編集し、マージまでしてみます。

# index.htmlを編集 
$ vi index.html

version1
version2
version3 #ここを追加

# コミット
$ git add index.html
$ git commmit -m "Version3"

# 一度masterブランチに移動する
$ git checkout master

# ver3ブランチをmasterブランチにマージする
$ git merge ver3

# マージされていることを確認
$ vi index.html

version1
version2
version3

GitHub初期設定

このままでは、ローカルで作業している人としかバージョン管理を行うことが出来ません。

なので、インターネットに接続できるリモートリポジトリを用意したいです。

これを提供してくれるのがGitHubというサービスです。

登録

まずはGitHubに登録してください。

認証方法

GitHubに対して「プル」や「プッシュ」を行う際の認証方法として、「アクセストークン」や「SSH認証」などがあります。

今回は「アクセストークン」を用いるので、ここのページを参考にアクセストークンを取得し、メモしておいてください

GitHubで共同開発

以上で共同開発に必要な準備が整いました。

ここからは、AチームとBチームの2チームを想定して進めてみます。

また、Aチームのリポジトリを親とします。

Aチーム(リモートリポジトリ作成 & プッシュ)

GitHubにサインインします。

「Repositories」の横の「New」を押下。

「Repository name」に「myweb」を入力し、「Create Repository」を押下。

これで空のリモートリポジトリが作成出来ました。

次に、今まで作業していたローカルリポジトリをこのリモートリポジトリにプッシュしてみます。

# GitHubのユーザ名とemailを登録する
$ git config --global user.name "ここにユーザ名"
$ git config --global user.email ここにメールアドレス

# GitHubのリポジトリをoriginという名前で登録
$ git remote add origin https://ユーザ名@github.com/ユーザ名/myweb.git

# ユーザ名・メールアドレス・URLが正しく登録されているか確認
$ git config -l

...
username=hoge #確認
user.email=hoge@hoge.com #確認
remote.origin.url=https://hoge@github.com/hoge/myweb.git #確認
...

# masterブランチに移動
$ git checkout master

# masterブランチをリモートリポジトリ(origin)へプッシュ
$ git push origin master

Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 205 bytes | 205.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/hoge/myweb.git
 * [new branch]      master -> master

上記のように表示されたら成功です。

※パスワードを聞かれたら、先程メモしておいた「個人アクセストークン」を入力してください。

これでローカルリポジトリをGitHubへプッシュすることが出来ました。

GitHubにアクセスし、index.htmlが存在することを確認してください。

Bチーム(Fork & Version3作成 & プルリクエスト)

次に、AチームのリポジトリをBチームのアカウントに完全コピーします。

このようなリポジトリの複製をForkと言います。

まず、BチームはAチームが先程作ったmywebというGitHubのページにアクセスします。

  • https://github.com/Aチームのユーザ名/myweb

次に、右上にある「Fork」というボタンを押下します。

そうすると、Bチームのアカウントに、mywebというリポジトリがそっくりそのまま作成されます。

また、BチームのmywebリポジトリのURLをコピーしておきます。

次に、Bチームの環境で、このリポジトリのクローンを作成します。

# 任意の場所へ移動
cd ~

# クローン作成
$ git clone https://github.com/bsann/myweb

# mywebへ移動
$ cd myweb

次に、Version3を作成し、コミットします。

# ブランチを切っておく
$ git branch ver3
$ git checkout ver3

# index.htmlを編集
$ vi index.html

version1
version2
version3 #ここを追加

# インデックスに追加
$ git add index.html

# コミット
$ git commit -m "Version3"

ではここで、ver3ブランチをBチームのリモートリポジトリへプッシュします。

# ユーザ名・emailを登録
$ git config --global user.name "ユーザ名"
$ git config --global user.email メールアドレス

# URLをoriginとして登録
$ git remote set-url origin https://Bチームのユーザ名@github.com/Bチームのユーザ名/myweb.git

# ver3ブランチをBチームのリモートリポジトリ(origin)へプッシュ
$ git push origin ver3

Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 246 bytes | 246.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: 
remote: Create a pull request for 'ver3' on GitHub by visiting:
remote:      https://github.com/bsan/myweb/pull/new/ver3
remote: 
To https://github.com/bsan/myweb.git
 * [new branch]      ver3 -> ver3

※同様に、パスワードを聞かれたら「個人アクセストークン」を入力します。

これでBチームのリモートリポジトリへプッシュすることが出来ました。

ここでBチームのGitHubへアクセスすると、次のような表示が出ますので、「Compare & pull request」を押下します。

※次のような画面が表示されない場合、「Pull request」タブを押下後、「New pull request」を押下

次のような文を記入し、「Create pull request」を押下します。

そうするとプルリクエストが完了し、Aチームがリクエストをマージすれば、AチームのリポジトリにVersion3が追加されます。

Aチーム(Version3をマージ)

Aチームのmywebページへアクセスすると、「Pull requests」にメッセージが表示されていので、それを押下します。

そうするとBチームからのプルリクエストが表示されるので、そちらを押下します。

Bチームのプルリクエストの内容に問題がなければ、「Merge pull request」を押下後、「Conform Merge」を押下します。

「Code」を押下し、「index.html」を見てみると、ちゃんとversion3が追加されていることが分かります。

以上で共同開発の一連の流れは完了です。