［GitHub］一人開発でもissueベース/セルフプルリクエストを使って開発する

# issueベース開発
サンデープログラマーにとってGitHubはmasterブランチで実装したものをpushしておくだけ。
いわば**ただのバックアップ置き場**になっている事も多いでしょう。
事実僕もちょっと前まではそうでした。

しかしWebサイトやWebアプリ開発をissueベースで行うと、**何をすべきかが明確**になります。
issueを実質的な「やることリスト・開発ロードマップ化」することで不要な実装や迷いがなくなり、開発スピードの向上が可能。
更に**issueから逆引きすることで、その機能を実装した時にどのようなコードを書いたか瞬時に判断**することができます。

一人でもGitHubのプルリクエストを使ってissueベースで安全に開発しましょう！

## 対象
- まだGit/GitHubに触れて日が浅い方
- 一人開発でGitHubの活用ができていない方
- 開発中あっちこっちの機能実装に浮気してしまい、効率的な作業ができていない方

既に最低限のgitコマンドが使える方を前提にしています。

# issue
![2020-07-10_12h33_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/ba887c31-5812-58ac-0d9e-2c518df2e407.png)

まずはissueを知っておきましょう。
これが実際のissueの画面、現在8つissueがあります。
issueは直訳すると「問題」という意味ですが、GitHub上におけるissueは「課題」と置き換えてよいでしょう。
これから何を行うべきか、どのようなことを検討すべきかをToDoリストのように管理できます。
issueを新規作成することを「issueを立てる（open）」、反対に作業が終わったら「issueを閉じる（close）」と言います。

## 固有のID管理
![2020-07-10_13h06_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/0b161fc0-f075-c038-b3bb-2df3f2a2759f.png)

タイトルの下に#40、#33のような`#番号`形式の記述があり、これはissueを示す固有のIDです。
つまり`#番号`を指定すればどのissueを指し示すのか簡単にわかり、GitHub上では`#番号`と記述すれば自動的にそのIDを持つissueにリンクが貼られます。
![2020-07-10_13h07_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/fb4364a2-a390-c1e8-19be-eb4fd7fc9cf7.png)


1. 機能追加のissueを立てる→issue ID `#1`
1. 機能追加が終わりissueを閉じる
1. 追加した機能のバグが見つかったので、バグ修正のissueを立てる
1. 1で立てたissueに関連するのでissue ID `#1`をコメントに含める

こんな感じでissueを立てれば、簡単に関連するissueにリンクを貼ることができます。
ワンクリックでその時何をしたのか確認できるので非常に便利ですね！

また、後述しますがコミットメッセージにissue IDを含めることでコミットが自動的にissue上にタイムライン形式で表示されるので、issueに対してどのようなコミットを行ったのか一目瞭然です。

## マークダウン記法に対応
![2020-07-10_12h02_46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/0bd30446-a3f9-eb45-139b-d135198208f4.png)

issueはマークダウン記法に対応しており、マークダウン記法を使って分かりやすいissueを立てることが可能です。
中でもチェックボックスはとっても便利。

```
- [ ] やること
- [ ] やること
- [ ] やること
```

このように書くことでチェックボックスが作成できます。
一つのissueに対して細かい作業をリスト化しておけば、何をやるかがより明確になりますよね。
例えばコミット単位で作業を区切ってリスト化する、みたいな感じで使うといいと思います。
終わった作業はチェックをつけることで擬似的に進行度がわかりますね。

他にもバグの再現画像を乗せたり、参考になるリンクだったりをマークダウンでぱぱっと書いてしまえば精度の高い管理ができそうです！

# Pull request
プルリクエスト（Pull request）は本来「こんな機能作ったよ！レビューして良かったらpullして（＝mergeしてよ！）」みたいな機能です。
が、当然セルフプルリクエスト運用は自分一人で行うのでコードのレビューとしての機能は（ほとんど）しません。
やってもいいけどそんなもんはエディタを見ればいいわけで、一人運用なのにGitHubでじっくりコードをレビューするなんてことはまあしないと思います・・・笑。

一人開発においてGitHubのプルリクエストを使う意義は、簡単にissueと紐付けが行えることです。
実はissueの固有IDはissueだけでなくプルリクエストと共用です。
つまり
1. `#1`のissueを立てる
1. 作業完了
1. プルリクエストを出す←`#2`の固有IDが発行される

こんな感じでプルリクエストにも固有のIDが付与されるので、issueと同じくプルリクエストに対してもGitHub上でリンクを貼ることが可能。
gitのGitHub管理を最大限活かすため、ローカルでのmergeではなくあえてGitHub上でmerge→後からfetchしてoriginとローカルブランチのmergeといった形にしています。
この辺は慣れてきたら一番理想的な方法を模索してみてください！

# issueベースのセルフプルリクエスト運用
それでは実際にissueを立ててセルフプルリクエストを出す、という一連の流れをやってみましょう！
大まかな流れは以下の通りです。

1. GitHub上でissueを立てる
1. ローカルでissue用のブランチを切る
1. 実際に作業する
1. 作業が終わったらissue用ブランチをgit pushする
1. git pushされたデータを元に親ブランチにプルリクエストを出す
1. GitHub上でプルリクエストをmergeしてissue用ブランチを削除する
1. ローカルで親ブランチをgit fetchしてmergeする
1. GitHub上でissueを閉じる

ブランチは以下を想定します。

- master
- *develop

現在機能開発用のdevelopブランチにいて、そこからissue用のブランチを切る運用です。

今回は.txtファイルを編集することを機能の実装と見立てて管理します。

なお既にローカルとGitHubの連携ができており、リポジトリの作成が完了、git push/fetchができる前提です。
ステージングやコミット等の細かい説明は割愛します、もしまだ曖昧という方は以下の記事も合わせて参考にして下さい。

[［git］Git逆引きチートシート/初心者向け - けんちゃん's tech blog](https://braveryk7.qrunch.io/entries/CXeuaRti6A0ZA93P)

## GitHub上でissueを立てる
![2020-07-10_13h51_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/baf1745b-ecfe-50a1-ff50-29ad69520009.png)

まずはissueを立てましょう。
入力項目はとりあえず最低限の4つを覚えます。

1. タイトル
1. 本文
1. アサイン（作業を行う人）
1. ラベル

タイトルと本文は自分が分かりやすいように書けばOKです。
先述した通りマークダウン記法が使えますし、`#番号`で既存のissueにリンクを貼ることもできます。

アサインは本来チーム開発において「○○さんにやってもらう」という割り振りが行えますが、一人開発なので「assign yourself」をクリックすれば自分が割り当てられます。

ラベルはひと目で「そのissueがどのようなものなのか」を表せます。
GitHubには元から9つのラベルが用意されています。

| ラベル名 | こんな時に使う |
| :---: | --- |
| bug | バグが発生した時 |
| documentation | ドキュメントの追加や改善 |
| duplicate | 既に同内容のissueがある |
| enhancement | 機能の追加や改善 |
| good first issue | （OSS等で）貢献したい人が最初に取り組むと良い |
| help wanted | ヘルプを求める場合 |
| invaild | 無効なissue |
| question | 質問 |
| wontfix | あえて改善しない |

一人開発で使うのは`bug`/`enhancement`/`wontfix`ぐらいでしょうか。
とりあえず機能の追加や改善は`enhancement`、バグを見つけたら`bug`、何らかの理由で改善を見送る場合は`wontfix`で良いと思います。
もちろん自分でラベルの作成もできるので、慣れてきたら分かりやすいラベルを作成して管理してもOKです！

![2020-07-10_14h16_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/ede351f7-b52a-e949-37b8-e49073b83e9b.png)


今回はこんなissueを立ててみました。
~~いかにも適当感溢れますね。~~

`Submit new Issue`をクリックするとissueが立ち、同時に`#番号`のIDが発行されタイトルの後ろに付与されます。

![2020-07-10_14h19_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/12e1782c-2023-0ee9-0bfb-f39996077c9f.png)


今回は`#2`が割り当てられました、今後この番号をチケット番号として使用するので覚えておいて下さい。

## ローカルでissue用のブランチを切る
それではローカルで今作ったissue専用のブランチを作成します。
ブランチ名はissue専用であることを分かりやすくするため、チケット番号を含めて命名しましょう。
例えば今回は`#2`なので、ブランチ名は`2`や`002`、`id/2`、`id/002`みたいなものが良いと思います。

```bash

//現在のブランチ確認
$ git branch
* develop
  master

//ブランチ作成とチェックアウトを同時に行う
$ git checkout -b id/002

//ブランチの作成と移動の確認
$ git branch
  develop
* id/002
  master
```

このissue専用ブランチはあくまでissueに対応したブランチなので、**issue外の作業は行わない**ようにしましょう。

## 実際に作業する
ブランチを切って専用のエリアを確保したので、ここでissueに対応する作業を行っていきます。

- あれ？今何の作業してたんだっけ？
- 今どこのブランチにいるんだっけ？

こんな場合は細く`git branch`コマンドで現在のブランチを確認しましょう。
ブランチ名にissueのチケット番号が含まれているため、ブランチ名を確認してissue一覧から同じ番号を見つければ簡単に現在の作業内容が明確になります。

作業が終わったらステージ、コミットします。
この時コミットメッセージにもチケット番号を含めましょう。

```bash
$ git commit -m "#2 献立記述"
```

これでコミットからもどのissueなのかを逆引きできるようになりました。
ちなみにチケット番号は先頭で無くても構いません。

```bash
$ git commit -m "コミットメッセージ #2"
$ git commit -m "コミット #2 メッセージ"
```

issueにチェックボックスをつけて作業進捗を管理する場合、適宜チェックボックスのチェックをオンにして分かりやすくしておきましょう。

ちなみにコミットに特定のワードを含めるとプルリクエスト完了後issueを自動クローズできますが、今回は初心者の方を想定して「あくまで慣れるため」なので実施していません。
慣れたらぜひオートクローズも試してみましょう！

## issue用ブランチをgit pushする
作業が全て終わりました！
それではGitHub上に以下の2点を反映させます。

- 新しくissue専用のブランチを作成したこと
- issue専用ブランチ内のコミット

```bash
$ git push origin id/002
```

![2020-07-10_14h35_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/19233d4a-7a56-0307-467d-92d5e311a1d1.png)

push後issueを見ると、下の方にコミットが紐付けられています。

## GitHub上でプルリクエストする
![2020-07-10_14h39_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/94aea265-158f-bbe7-430d-81eddaa001df.png)


続いてissue専用ブランチを親ブランチであるdevelopブランチにプルリクエストします。

![2020-07-10_14h40_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/60598be2-fa8d-eb11-d512-9b7e63af8ec5.png)


プルリクエストはissueと同じように作成できますが、なんと最近pushしたブランチを表示してくれています。
Compare & pull requestをクリックしてブランチからプルリクエストを作成しましょう。

![2020-07-10_14h52_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/723bcdd6-967a-db23-1ec0-e7e11e3e0fd3.png)


プルリクエストはissueと似たようなフォームで作成できます。
本来ならプルリクエストの目的や理由、詳細を書きますがどうせ見るのは自分です。
分かりやすく書いてあればそれでOKぐらいの気軽なノリでいきましょう！

一点気をつけて欲しいのが画像内赤枠で囲った部分。
これは**どのブランチがどのブランチを取り込むか**を指定します。
今回は`developブランチ`が`id/002ブランチ`を取り込むため、必ずブランチの指定を確認してください。

入力が終わったらCreate pull requestをクリックしてプルリクエストを作成します。

## GitHub上でプルリクエストをmergeしissue用ブランチを削除する
![2020-07-10_14h57_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/ca7b59bb-b51f-1142-d9b9-1227200fe27b.png)


プルリクエストを作成後、ページ下部にこんな感じの表示が現れます。

![2020-07-10_15h04_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/b400d6af-b9c7-cdf2-19c8-bd8be2eeb389.png)


Merge pull requestをクリックすると親ブランチで取り込みが行なえます、Confirm mergeをクリックしてマージしましょう！

![2020-07-10_15h05_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/1e540121-481d-fc3a-5534-53a9ae98a7f3.png)


マージが完了するとissue専用ブランチをGitHub上で削除するボタンが出現します。
基本的にマージ完了後は使用しないので、Delete branchボタンをクリックしてブランチを削除します。
もしマージ完了後新たに関連して作業が必要になった場合、改めてissueを立てると良いでしょう。

## ローカルで親ブランチをgit fetchしてmergeし、issue用ブランチを削除する
今の状況を整理しておきます。

| 場所 | 状況 | 
| :---: | --- |
| ローカル | issue専用ブランチにいて、issue専用ブランチをpushした |
| GitHub | issue専用ブランチをdevelopブランチに取り込み、issue専用ブランチを削除した |

つまりGitHub上ではdevelopブランチが最新状態、ローカルが遅れをとっているイメージです。
developブランチに移動後GitHubのdevelopブランチを取得して反映、その後不要になったissue専用ブランチを削除しましょう。

```bash
//developブランチに移動
$ git checkout develop

//ブランチ確認
$ git branch
* develop
  id/002
  master

//GitHubのdevelopブランチをローカルのorigin/developに反映
$ git fetch origin develop

//origin/developをdevelopに反映
$ git merge origin/develop

//issue専用ブランチを削除
$ git branch -d id/002
```

これで今回issueを立てた全ての作業が完了しました！

## GitHub上でissueを閉じる

![2020-07-10_15h17_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/468367aa-7cef-393e-0509-f05317f44d12.png)


それでは最後に全て終了したissueを閉じましょう。
issueの下部のコメント欄にClose issueボタンがあるのでクリックして終了です！
お疲れさまでした！

![2020-07-10_15h19_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601080/acc0fdf4-db75-0d72-69d6-dc418252640f.png)


なお過去閉じたissueも、issue一覧からClosedをクリックすることで確認することが可能です。
Close＝削除ではないので安心して閉じてOKです。

# masterブランチ1本からの進歩
ここまで来たのに身も蓋も無いことをぶっちゃけ言うと、個人開発なんてmasterブランチ1本で十分っちゃ十分です。
誰かが並行して編集することが無いのでコンフリクトが起こることもないですし。

ただあくまで僕の場合はやることを明確化することでなにが必要か、なんのためにやるのか、どういう手順なのか。
この辺りが非常に明確になりました。
ふと閃いたけど実装したとしてもかなり先になるであろう機能もissueを立てることで忘れずに済みます。
ただしそれを面倒だと感じるのであればいつでも元のmasterブランチ1本運用に戻しても良いと思います、そのぐらいハードルを低くしても全然OK。

どうせgitとGitHubを使うなら、もう一歩踏み込んで使ってみると更に便利だから試しにチャレンジしてみると良いと思います。