GitHubハンズオン 第2回 〜共同開発編〜

# GitHubハンズオン 第2回 〜共同開発編〜

本記事は、GitHubハンズオンの第2回の資料です！
第1回を読んでいることを前提としていますので、まだ読んでいない方は、先にそちらをお読みください。


##### GitHubハンズオンシリーズ

- [GitHubハンズオン 第1回 〜個人開発編〜](https://qiita.com/segur/items/601277fbbe8cfa08678b)
- GitHubハンズオン 第2回 〜共同開発編〜 ← 本記事
- [GitHubハンズオン 第3回 ～ブランチ運用法編～](https://qiita.com/segur/items/1dd578003da46bddc117)
- [GitHubハンズオン 第4回 ～いろいろ取り消し編～](https://qiita.com/segur/items/8ce6914af5578c5f4ce2)
- [GitHubハンズオン 第5回 ～無視リスト編～](https://qiita.com/segur/items/2de61acfa73ce1eceac9)
- [GitHubハンズオン 第6回 ～巨大ファイル編～](https://qiita.com/segur/items/347345a489a963641306)


# 共同開発したい

第1回では、個人開発に焦点あてたハンズオンを実施しました。
第2回では、複数人での共同開発に焦点をあてます。

ハンズオン資料なので、 **複数人で同時に作業することを想定した内容** になっています。
もし、 **お一人でハンズオンに取り組む場合は、複数のローカルリポジトリを作って作業する** ようにお願いします！


# リポジトリをクローンする

今回は以下のリポジトリを使いたいと思います。

https://github.com/segurvita/GitHubHandsOn

このリポジトリをPCにクローンしてください。
（クローンの手順を忘れてしまったら、 [第1回](https://qiita.com/segur/items/601277fbbe8cfa08678b#%E3%82%AF%E3%83%AD%E3%83%BC%E3%83%B3%E3%81%99%E3%82%8B) を読み返してください。）

こちらは私が作ったリポジトリでして、とくに危険なプログラム等は含まれておりませんが、気になる場合は、ご自身でリポジトリをご用意ください。
その場合、README.mdファイルをコミットしておいてください。


# ブランチを作る


## ブランチとは

ここまでは、編集履歴を1本の流れのように扱ってきました。

しかし、ブランチ機能を使うと、編集履歴の流れを分岐させることができます。

たとえば、アイデアAとアイデアBのどちらを採用すべきか悩むような場面はよくあります。そんなときに、ブランチは効果を発揮します。

以下の図のように、mainブランチから2つのブランチを作ります。


* `feature/try-idea-a` : アイデアAを試すためのブランチ
* `feature/try-idea-b` : アイデアBを試すためのブランチ


図は右に行くほど、新しいコミットになります。


![image14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/4f511162-ec9f-e1ee-f391-eb54924ad987.png)


それぞれ、実際にファイルを編集しますが、mainブランチに影響することはありません。

「実際に試してみたら、アイデアBがよさそう」となったら、 `feature/try-idea-b` ブランチを `main` ブランチに取り込みます。

この取り込み作業を **マージ** と呼びます。

作業ディレクトリとの関係は以下のようになります。

```mermaid
graph LR
    subgraph PC
        subgraph ローカルリポジトリ
            main[mainブランチ]
            feature[featureブランチ]
        end
        workingDirectory[作業ディレクトリ]
    end
    main -->|branch| feature
    feature -->|checkout| workingDirectory
```


ブランチの内容を作業ディレクトリに反映させることを **チェックアウト** と呼びます。

図書館から本を借りることを、英語で **check out** と言います。
リポジトリ（貯蔵庫）からファイルを借りて、手元に置いてるイメージです。


## ブランチを作る


![image37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/cabe852a-ce41-7f73-c30a-740b38387c95.png)


Forkの上部にあるBranchをクリックすると、ダイアログが表示されます。

**Branch name** 欄に、 **自分のユーザー名/practice** を入力してください。
（お一人でハンズオンを進めている場合は、ローカルリポジトリ毎にブランチ名を変更してください。たとえば、ユーザー名の末尾に数字を付ける等です。）

**Checkout after create**にチェックを入れて、**Create and Checkout**ボタンをクリックしてください。

mainの隣に、自分の作ったブランチが表示されていれば成功です！


![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/55b607b7-b156-ac31-842f-01b199b60a26.png)


以後、このブランチを本書では **practiceブランチ**と呼ぶことにします。


## ファイルを作成する

作業ディレクトリを開いてください。
（開き方を忘れた場合は、 [第1回](https://qiita.com/segur/items/601277fbbe8cfa08678b#readmemd%E3%82%92%E4%BD%9C%E3%82%8B) を読み返してください。）

README.mdの隣に新しいテキストファイルを作成し、ファイル名を自分の名前にしてください。


![image8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/5e37966c-7289-e0ef-3993-3da071f63f92.png)


## ブランチにコミットをする

ファイルが作成できたら、コミットしてください。
（コミットの方法を忘れた場合は、 [第1回](https://qiita.com/segur/items/601277fbbe8cfa08678b#%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%99%E3%82%8B) を読み返してください。）

以下のように、practiceブランチにだけコミットが追加され、mainブランチには追加されていないことがわかります。


![image26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/ef922d5b-ff61-a460-de6d-7e6b7fddd9ef.png)


ここで、もしmainブランチにコミットが追加されている場合は、practiceブランチのチェックアウトができていませんので、チェックアウトしてください。


## ブランチをPushする

画面上部の **Push** ボタンをクリックすると、ダイアログが出てきます。


![image6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/8686fabe-ee55-cbff-3edb-7f4c930eba85.png)


そのまま **Push** ボタンをクリックすると、プッシュが開始されます。

以下のように、GitHubのアイコンがpracticeブランチに付いたら、Push成功です！


![image31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/5321c39d-6961-a24f-4ef5-6770b2902096.png)


# フェッチする


## フェッチとは

リモートリポジトリにあるブランチを、PCのローカルリポジトリにコピーすることを **フェッチ** と呼びます。

```mermaid
graph LR
    subgraph PC
        subgraph ローカルリポジトリ
            local[ローカルブランチ]
        end
    end
    subgraph GitHub
        subgraph リモートリポジトリ
            remote[リモートブランチ]
        end
    end

    remote -->|fetch| local
```


**fetch** は、遠くにある物を取りに行って持って帰るという意味の英単語です。


## フェッチする

画面上部の **Fetch** ボタンをクリックすると、ダイアログが表示されます。

`Fetch all remotes` にチェックを入れた状態で、 `Fetch` ボタンをクリックすると、フェッチが始まります。


![image23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/9afce2e4-bae7-879f-f56b-fa9f66e7b5b8.png)


以下のように、他のメンバーのpracticeブランチが表示されれば成功です！


![image38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/26e258e0-1326-3b8e-aaf4-66981d32ca7a.png)


## 他のメンバーのブランチをチェックアウトする

他のメンバーのブランチを**右クリック > ブランチ名 > Checkout** をクリックします。


![image25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/d56779c6-1b11-9207-1cef-4f93f817c1a4.png)


ダイアログが表示されるので、そのまま **Track** をクリックします。

![image7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/89ccfffb-a9cb-3cbb-dff2-a7935db3dd66.png)


以下のように、他のメンバーのブランチに✓がつけば成功です。


![image46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/9459e23f-f9a3-b564-97cb-111c038c310f.png)


作業ディレクトリを開くと、以下のように、他のメンバーのコミットした内容が復元されています。


![image22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/01863d60-6d15-8142-b6b5-af941cca2c54.png)


# マージする


## mainブランチをチェックアウトする

mainブランチをチェックアウトしてください。
（チェックアウトの方法を忘れた場合は、本書を読み返してください。）


## 1人目がpracticeブランチをmainブランチにマージする

ここからは1人ずつ作業します。

1人目は、自分の名前のpracticeブランチを右クリックして **Merge into ‘main’** をクリックしてください。


![image28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/77202b4e-01ea-c192-b944-c9f03f97ab3f.png)


以下のようにダイアログが表示されます。

**Merge Option** を **No Fast-Forward** に変更してください。（以後の説明をわかりやすくするためです。）

**Merge** ボタンをクリックします。


![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/5d811a06-a59d-fb9b-dd1b-d9f056bac2bc.png)


以下のように、自分の名前のpracticeブランチがmainに合流したら成功です！

この作業をマージと呼びます。


![image40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/71bbec8e-6b1c-441b-35c5-58d18fc08f3d.png)


マージできたら、mainブランチをプッシュしてください。

（プッシュの方法を忘れた場合は、 [第1回](https://qiita.com/segur/items/601277fbbe8cfa08678b#%E3%83%97%E3%83%83%E3%82%B7%E3%83%A5%E3%81%99%E3%82%8B) を読み返してください。）


## 他のメンバーがフェッチしてmainブランチを更新する

他のメンバーは、フェッチをして、最新のmainブランチを取得してください。

以下のような状態になっているはずです。


![image21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/80601a5e-e3d7-784a-93ee-c78cf882ba5b.png)


`origin/main` となっている箇所をダブルクリックすると、以下のようなダイアログが表示されます。


![image34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/16c0a2c3-87b5-d609-12f9-c807c1d0cce6.png)


そのまま **Checkout and Fast-Forward** ボタンをクリックします。

すると、以下のように `main` ブランチが一番上に移動します。


![image17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/ae99f84b-c7b6-e6d9-1968-9456a5379eb1.png)


## 他のメンバーがpracticeブランチをマージする

ここで、2人目の出番です。

自分の名前のpracticeブランチをmainブランチにマージして、プッシュしてください。

プッシュが終わったら、他のメンバーはフェッチをして、mainブランチを更新します。

この作業をハンズオンのメンバー全員分実施します。

最終的には以下のように、すべてのブランチがmainに合流します。


![image47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/b73c78ff-8596-07df-a622-5ebe52d4da5c.png)


作業ディレクトリを見ると、以下のようにすべてのメンバーのファイルが表示されます！


![image36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/322042a4-55c5-54cb-163c-539fb1aec161.png)


このように、マージ機能によって、複数のメンバーの編集履歴を統合できます。

これにより、共同開発が可能になります。


# 競合について

もし、2人が同じファイルを編集してコミットしたらどうなるのでしょうか？

**競合**という現象が発生します。

競合を解決するためには、2つのブランチを見比べて、つじつまを合わせるための新しいコミットを追加する作業が必要になります。

非常に手間のかかる作業なので、競合はなるべく避けるべきです。

そのためにも、同じファイルを編集しないようにする工夫が必要なります。

以下は、競合を避けるための工夫です。


## フォルダー構造を明確にする

フォルダー構造を明確にし、誰がどのフォルダーを触るのか、担当を決めることが大事です。


## 自分の担当外のファイルを編集する場合は声をかける

自分の担当外のファイルを編集したい場合は声をかけることで、競合を避けましょう。

声をかけるとは、Slack等で連絡してもいいですし、PullRequestというGitHubの機能を利用する場合もあります。

（PullRequestは今回のハンズオンでは扱いません）


## こまめにフェッチする

mainブランチはメンバー全員が自分の作業を日々反映させるため、非常に速いスピードで変化します。

その変化に追いつくため、こまめなフェッチが大事です。


## ブランチをこまかく作って、こまめにマージする

mainブランチから分岐してから、長い時間が経つと、競合が発生しやすくなります。

1つのブランチでたくさんの作業をせずに、細かい単位でブランチを作り、こまめにマージすると、競合を防ぐことができます。


# さいごに

今回はここまでです！おつかれさまでした！

次回はブランチ運用編です！引き続きこちらも実践していただけると嬉しいです！

https://qiita.com/segur/items/1dd578003da46bddc117