GitHub の Issue と Pull request の記載内容をテンプレート化する全手順と、実際のテンプレートのサンプル

## 概要
GitHub の Issues と Pull request（PR）の記載内容を、事前にカスタマイズした内容でテンプレート化する方法についての備忘録。

また、実際にテンプレートとして用意したものを、サンプルとして記事内で紹介する。

### 前提
- Git / GitHub についての基本概念は説明しない
- Issue(s) / Pull request(s) も、ここで詳細には説明しない

### 想定する対象読者
- GitHub をより効率的に使いたいと思っている方
- GitHub をチーム開発に利用している、チームまたは企業・団体
- 個人開発だけど、バージョン履歴をキレイにしたい方

## テンプレート化のメリット
Issue と Pull Request（PR）のテンプレートを用意できる様になると、何が嬉しいのかを簡単にまとめる👇

### 概念のおさらい

- **Issue（イシュー）**：GitHub で **「課題」** を管理する機能。「課題」とは主に以下
    - 新しく追加したい機能・画面
    - 既存機能の修正
    - バグや報告された不具合
    - フィードバック等の意見など
- **Pull request（プルリクエスト）**：メインブランチから作成された、新規機能やバグ対応等の「作業ブランチ」を、対応後に再びメインブランチに統合（マージ）されることを要求する、**「統合要求」** 機能

### 通常はこういう状態
GitHub メニューの「Issues」タブを選択し、「New issue」ボタンから新規作成すると、通常は、以下のように完全に空白な入力画面になる。

![GitHub_テンプレ化_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/00883f94-dafd-4916-a248-10efc5f2d8b4.png)

![GitHub_テンプレ化_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/7775fb68-a8b9-418a-95e2-449e1e8831c4.png)

これは、Pull request を作成する場合も同様（Pull requests タブの「New pull request」ボタンから作成）。

![GitHub_テンプレ化_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/f9daee42-1909-47df-99e1-4647a2f6d5b0.png)

### テンプレート化した時の状態
今回説明する「テンプレート化」を実施すると、以下の様に事前に決めたテキストを埋め込んでおくことができる。

**Issue**
![GitHub_テンプレ化_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/bdda94a2-849e-4404-bb8f-05b50a58afca.png)

**Pull request**
![スクリーンショット 2025-03-17 9.42.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/0e8dde4a-1d59-4222-9785-d8be461e0032.png)


### テンプレート化すると何が嬉しいの？

- チーム開発をする場合、チームメンバーで書き方が統一される
  - PM、チームリーダーなど、管理側が確認しやすくなる
  - 開発者も書き方が統一され、記載も楽になる
- チーム開発で「人の入れ替わり」が発生した際、新規参画者に対する説明・フォローのコストが少し減る
- 個人開発でも、後からチーム開発にスケールすることを想定する場合は、最初からこれらをテンプレート化しておくと、同様の恩恵を得られる

個人開発は、コミットテンプレートも作成は可能なので、ひとまずコミットだけで済ませた方が短期的には気楽だが、
そもそも Issue は個人開発でも有用であるし、Pull request は Issue と連動させることができるので、後から過去の内容を追いかける場合に一貫性を持ちやすくなる。

## 手順（Issue）

### Web 画面から直接設定する手順
- GitHub リポジトリのメニュータブ「Setting」を選択し、左のサイドメニュー「General」を選択
- 表示される設定項目から「Features」欄を探し、Issues の「Set up templates」を選択する

![GitHub_テンプレ化_06_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/99206f8b-3377-4ca0-8bd3-6f2c1d876c35.png)

もし、Issues にチェックが入っていないと、下記のようにボタンが表示されていない状態になるので、その時は Issues にチェックを入れてから画面を再表示する
![GitHub_テンプレ化_06_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/c1ca7adf-101f-452f-a5ca-5bba6a932f96.png)

- 画面遷移するので、選択肢からテンプレートを選択する
  - Bus report（バグ・不具合を報告する時のサンプル形式）
  - Feature request（機能開発を想定したサンプル形式）
  - Custom template（自分で内容を決めるカスタム形式）

今回は、自分で内容を決めるので「Custom template」を選ぶ

#### 実際のテンプレート・サンプル
※ 「テンプレート名」と「説明」はテンプレート管理用の設定項目なので、実際の Issue には表示されない

**テンプレート名**（Template name）
```
Generic Issues
```
※ もちろん日本語でもOK 👍

**説明**（About）
```
汎用的な Issue テンプレート
```

**内容**（Template content）
```md
※ 各項目の説明欄を削除して内容を記載する。対応後、この説明文と省略可能な（Opt.）項目は削除する

## As is
現状を記載（対応しないことで発生する課題）

## To be 
理想状態を記載（タスク完了条件に相当）

## Requirements
（Opt.）対応に必要な前提条件や決めるべき事がある場合のみ、箇条書きで記載

## Actions
（Opt.）対応する流れやアクションを詳細に書く場合のみ、箇条書きで記載
```

追加の詳細設定（Optional additional items）は下記

**Issue デフォルトタイトル**（Issue default title）
```
〇〇したい
```

**Assignees**（デフォルト担当者）：未設定
**Labels**（管理タグ的なやつ）：未設定

上記、設定が完了したら、右上の「Propose changes」ボタンを押下

コミットが発生するので、適当なメッセージを残して「Commit changes」で確定する（今回はメインブランチに直接マージした例）
![GitHub_テンプレ化_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/e964ab7a-1151-487a-ae58-323cb5dee7d6.png)

下記のようにリポジトリに `.github/ISSUE_TEMPLATE` が作成されていれば作成完了
![GitHub_テンプレ化_09_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/f03177b5-986a-4442-b594-29c907691805.png)

### ローカル環境から設定する方法
上記の完了後のリポジトリを見るとわかるが、
要するにリポジトリの規定フォルダに仕様に沿った設定ファイルを用意してコミット・プッシュするだけ。

![GitHub_テンプレ化_09_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/049549ae-0ee5-4905-9299-c41909fca280.png)

- リポジトリに `.github` という隠しディレクトリを用意
- その直下に `ISSUE_TEMPLATE` というディレクトリを用意
- 更にその配下に `xxxxx.md` というテンプレートをマークダウンで用意する

この時に用意するマークダウンの書き方は以下の通り

**マークダウン（.md）ファイル** のサンプル
```md:.github/ISSUE_TEMPLATE/generic-issues.md
---
name: Generic Issues
about: 汎用的な Issue テンプレート
title: 〇〇したい
labels: ''
assignees: ''

---

※ 各項目の説明欄を削除して内容を記載する。対応後、この説明文と省略可能な（Opt.）項目は削除する

## As is
現状を記載（対応しないことで発生する課題）

## To be 
理想状態を記載（タスク完了条件に相当）

## Requirements
（Opt.）対応に必要な前提条件や決めるべき事がある場合のみ、箇条書きで記載

## Actions
（Opt.）対応する流れやアクションを詳細に書く場合のみ、箇条書きで記載
```

上記ファイルを作成してリポジトリにプッシュ/main ブランチにマージすれば、設定完了する。

### 設定完了すると
「New issue」を作成するときに、下記の様にテンプレートを選択できる様になる

![GitHub_テンプレ化_10_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/8e06289a-fc38-46be-8a1a-287a3d50f48c.png)

### 選択肢をなくして１つに固定できないの？
テンプレートを用意すると、「自分が用意したテンプレート」＋「空の Issue で作る」の２つが表示される。

これを、**「New issue」ボタン押下後、選択肢を表示することなく、カスタムテンプレートですぐに編集画面が表示される様にできないか？** というと、結論、**できない** 。
（※ もし、方法をご存知の方がいたらご教示ください🙏）

しかし、**選択肢は表示されてしまうが、１つにする** ことはできる。

方法は、`.github/ISSUE_TEMPLATE/` の中に `config.yml` という設定ファイルを用意し、中身を以下の通りにするだけ。

```yaml:.github/ISSUE_TEMPLATE/config.yml
blank_issues_enabled: false
```

ファイルを用意するには、ローカルからコミットしても良いし、下記の様に Web UI からファイルを直接追加してコミットしても良い。

![GitHub_テンプレ化_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/d1bafca8-5736-4f94-a7d8-1a8db9142a36.png)


### YAML ファイルのフォーム形式とは違うの？
テンプレート設定に関して、他の記事や公式ドキュメントを見ると、YAMLファイルで用意する方法が出てくるが、結論、マークダウンで用意するのとではちょっと違う。

- **マークダウン（.md）ファイル**：「Issue テンプレート」
- **YAML（.yml）ファイル**：「Issue フォーム」

テンプレート設定において、YAML ファイルは「Issue テンプレート内容そのもの」ではなく、**「フォームを作成するもの」** である。

詳細は割愛するが、最初に提示したテンプレートと同様の内容にする YAML ファイルをルールに従って用意すると、中身は下記の様になる。

**YAML（.yml）ファイル** のサンプル
```yaml:.github/ISSUE_TEMPLATE/generic-issues2.yml
name: Generic Issues 2
description: 汎用的な Issue テンプレート
title: "〇〇したい"
labels: []
assignees: []
body:
  - type: textarea
    id: as-is
    attributes:
      label: As is
      description: 現状を記載（対応しないことで発生する課題）
      placeholder: ユーザーを管理できない
      value: ""
    validations:
      required: true
  - type: textarea
    id: to-be
    attributes:
      label: To be
      description: 理想状態を記載（タスク完了条件に相当）
      placeholder: ユーザー管理画面を実装したい
      value: ""
    validations:
      required: true
  - type: textarea
    id: requirements
    attributes:
      label: Requirements
      description: 対応に必要な前提条件や決めるべき事がある場合のみ、箇条書きで記載
      placeholder: |
        - 〇〇定義をまとめた一覧を用意する
        - IF 仕様を確定する
        - 画面 ID を決定する
      value: ""
    validations:
      required: false
  - type: textarea
    id: actions
    attributes:
      label: Actions
      description: 対応する流れやアクションを詳細に書く場合のみ、箇条書きで記載
      placeholder: |
        - 〇〇設計書作成 / 内部レビュー
        - UT のテストコード実装
        - バックエンド：API 実装
        - フロントエンド：コンポーネント・サービスクラス実装
      value: ""
    validations:
      required: false
```
※ 上記は、マークダウンファイルのサンプルと同じ値が含まれているが、重複はできないため、混在しない様に「ファイル名」および１行目の「name」は別の名前にしている。

上記によって、テンプレート選択後に以下の「フォーム」が表示される。

![GitHub_テンプレ化_12_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/54972bd6-c9e9-4421-be9d-0a631343f6f7.png)

![GitHub_テンプレ化_12_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/dc34af93-ae36-4a6a-b749-b09b73eca6c6.png)

上記フォームに内容を入力して確定すると、以下の様に Issue が作成される。

![GitHub_テンプレ化_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/d553cf7b-f9ae-47e2-b8ba-a789a1fbfb5a.png)

### 表示順序を変える方法
Issue テンプレートの表示順序は「ファイル名の昇順」となるため、テンプレートのファイル名以下の様にするのが最もシンプル。

- `1-issues_template.md`
- `2-issues_template.md`
- `3-issues_template.md`

ただし、10 を超える場合は、数字部分の桁数を合わせて `01-`、`02-` とゼロ埋めしなければならない。

- `01-issues_template.md`
- `02-issues_template.md`
- `11-issues_template.md`

桁数を合わせないと、以下の様になってしまう。

- `1-issues_template.md`
- `11-issues_template.md`
- `2-issues_template.md`

## 手順（Pull request）

### Web 画面から直接設定する手順
以下の手順で、`.github/` ディレクトリの直下に、固定ファイル名 `pull_request_template.md` を用意する。

![GitHub_テンプレ化_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/d1bafca8-5736-4f94-a7d8-1a8db9142a36.png)

ファイルの中身は以下の様に適当に用意する。

**PR テンプレートのサンプル**
```md:.github/pull_request_template.md
~~~md
※ 各項目の説明欄を削除して内容を記載する。対応後、この説明ブロックと省略可能な（Opt.）項目は削除する
タイトルは以下の形式でプレフィックスを付与する
新規追加： `[feat] add: 機能名・画面名など`
既存改修： `[feat] fix: 変更の概要`
バグ対応： `[bug]: 不具合事象の概要`
~~~

## Why
この PR が発生した背景（以下例、またはチケットURLを記載）

resolves #<Issue 番号>

## What
変更の目的を記載（例）ユーザー認証フローにおけるセッションタイムアウトの問題を修正

## How
変更内容を記載（以下例）
- ユーザーが一定時間アクションを起こさないとセッションが無効になり、その後再ログインを求められるように変更
- セッションタイムアウトの設定を `config` ファイルで調整可能にした

## Test
テスト方法を記載（以下例）
- ユーザーが一定時間操作しない場合に、セッションがタイムアウトし、再ログイン画面が表示されるか確認
- または <テストケース説明資料のリンク>
```

PR を作成した時に、誰でも同様の形式となるように中身を考えてみるのがポイント。

#### 補足：Issue 連動キーワード
上記サンプルの `resolves #<Issue番号>` （例：`#10`）様に、Issue 番号と共に既定キーワードを設定することで、この PR がマージされた時に自動で関連 Issue がクローズするなどの挙動をさせることができる。

また、これは「説明欄」だけではなく、「タイトル」「コミットメッセージ」に含めても同様に動作する。

詳細は [公式ドキュメント](https://docs.github.com/ja/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue) を参照

※ ただし、「PR マージ ＝ Issue クローズ」とすべきかはケース・バイ・ケースになるため、テンプレートの書き方は工夫が必要かもしれない。

上記をコミットしたら、テンプレートの作成は完了する。

### ローカル環境から設定する方法

上記と同様のファイルを、ローカル環境で用意してコミット・プッシュするだけ。

### 複数の PR を選択できる様にしたい場合
Issue のように `PULL_REQUEST_TEMPLATE` というサブディレクトリを用意して  `.github/PULL_REQUEST_TEMPLATE/テンプレート名.md` とすると複数用意できる。この場合、ファイル名は固定ではなく任意にできる。

ただし、実際に選択する場合は、PR 作成時の URL に、以下のように「クエリでテンプレートを指定する」というひと手間が発生してしまう。

```
<PR の URL>?template=テンプレート名.md
```

## まとめ

- Issue のテンプレートは、リポジトリに以下の様にマークダウンファイルを用意する
  - `.github/ISSUE_TEMPLATE/テンプレート名.md`
- テンプレート選択時の表示順序を変えるには、ファイル名の先頭に数字などを付与する
- Pull request のテンプレートは、リポジトリに以下の様に「固定ファイル名」でマークダウンファイルを用意する
  - `.github/pull_request_template.md`
  - `doc/pull_request_template.md`
- 複数の Pull request テンプレートを用意する場合は、以下の様にディレクトリを用意して、その中に「任意のファイル名」でテンプレートファイルを管理する
  - `.github/PULL_REQUEST_TEMPLATE/テンプレート名.md`
  - `doc/PULL_REQUEST_TEMPLATE/テンプレート名.md`