最初のcommitでテンプレートに沿ってPull Requestのコメントをほぼ一発で書き上げるには

# :warning: はじめに

記事を書きましたが、同じことは[hub](https://github.com/github/hub)のpull-requestコマンドでできます (あとから知った)
なので「あえて手動でやってみるなら」というのに興味がある方は見て下さい。

---

# 概要

GitHubの仕様で「マージ先との差が1commitの場合に限りPull Requestのタイトルとコメントをcommitメッセージから自動入力してくれる」というものがあります。
commitメッセージの1行目がタイトルに、3行目移行がコメントにそれぞれ対応しています。
これを利用し「ブランチ作成時に空commitを作ってGitHubへpushしそのままPull Requestを作成する」という運用をしている方は多いかと思います。

```plaintext:COMMIT_EDITMSG
1行目はPull Requestのタイトルになる

3行目以降は
Pull Requestのコメントになるので
ここをPull Request Templateで埋めたい
```

一方commitメッセージの1行目は書いても、3行目以降でコメントまで書いてからpushするという方はあまり多くないのではないでしょうか。
そこで今回、少しだけgitに設定を加えることで、ローカルでテンプレートに沿ってPull Requestを書き上げ、Web上ではボタンクリック1発でほぼ完成させられるようにしてみました。 (「ほぼ」の理由は最後に記載してます)
個人的にはそれなりに便利になったと思ったのでやり方を紹介します。

# 設定方法

今回設定で使用したのは以下の機能です、順を追って説明します。

- commit template
- git config alias
- git config core.commentchar

## gitのcommit template機能

gitでは、commit時にテンプレートファイルを指定することができます。
指定の方法にはgit configに書き込む方法と、commit時に `-t` オプションを渡す方法があります。
それぞれの違いは下記の通りで、前者だとテンプレートはグローバルまたはリポジトリ内で固定、後者はcommit毎にテンプレートを指定できます。

|設定方法|有効範囲|指定タイミング|
|:---:|:---:|:---:|
|`git config —global commit.template`|全リポジトリ|固定|
|`git config —local commit.template`|現在のリポジトリ|固定|
|`git commit -t path/to/template`|現在のリポジトリ|commit毎|

今回の要件は「初回のcommitのみ」テンプレートが必要なので `git commit -t` を使うことにします。
オプションの引数にテンプレートファイルのパスを指定すると、内容がcommitメッセージに反映されます。
もしGitHubに `PULL_REQUEST_TEMPLATE.md` が存在するならそれを指定すればよいわけです。

```bash
git commit -t path/to/repo/.github/PULL_REQUEST_TEMPLATE.md
```

こうするとGitHubと同じテンプレートでcommitメッセージに書き込むことができます。

### git aliasで楽にする

とはいえ、このパスを含めたコマンドを毎回手入力するのは大変です。
そこでgit aliasで新しいコマンドを設定します。
今回は `git ct` というコマンドでできるよう `.gitconfig` に追記します。

```bash:ctコマンドを設定
[alias]
  ct = !"git commit -t ./.github/PULL_REQUEST_TEMPLATE.md"
```

これでも動作はしますが、さらに以下を加えてみます。

* 現在のリポジトリのルートを `git rev-parse --show-toplevel` で動的に取得し、任意のリポジトリかつルート以外でも実行可能にする。
* テンプレートファイルの存在を判定し、存在しない場合はエラーメッセージを表示。

```bash:判定も加えたバージョン
[alias]
  ct = !"TEMPLATE_PATH=$(git rev-parse --show-toplevel)/.github/PULL_REQUEST_TEMPLATE.md; if [ -e ${TEMPLATE_PATH} ]; then git commit -t ${TEMPLATE_PATH} ; else echo "PULL_REQUEST_TEMPLATE.md is not defined so commit aborted."; fi"
```

### commitメッセージでmarkdownを使えるようにする

これでテンプレートをcommitメッセージに流し込めるようになりましたが、commitメッセージで `#` はコメントを表す識別子になるため、markdownのヘッダーはコメントとして扱われてしまいます。
例えばPull Request Templateが以下のようになっている場合、TODOやMEMOの行はコメントと認識されて消えてしまいます :sweat: 

```markdown:PULL_REQUEST_TEMPLATE.md
# 概要

## TODO <- コメントとしてメッセージから消える

- [ ]

## MEMO <- コメントとしてメッセージから消える

- 
```

そこで再びgit configで、コメント識別子を `#` 以外(今回は `;` )に変更してみます。
これは `git config core.commentchar` で変更することができます。

```bash
[core]
  commentchar       = ";"
```

こうすることでmarkdown記法とバッティングしなくなるので、これで無事テンプレートを使ってcommitメッセージを書くことができるようになりました!
ただテンプレートは1行目から始まってしまうので頭で改行は必要です 💦

```markdown:COMMIT_EDITMSG
# 概要

## TODO

- [ ]

## MEMO

- 
; Please enter the commit message for your changes. Lines starting
; with ';' will be ignored, and an empty message aborts the commit.
;
; On branch master
; Your branch is up to date with 'origin/master'.
;
; Changes to be committed:
;	modified:   Brewfile
;

```

## デモ

最後に実際のデモです。
さすがにファイルアップロードはローカルではできませんが、テキストであればローカルで書き上げることができますね!
コミットメッセージにこのような情報を書くということ自体が良いことかという議論はありますが、秘匿情報等が入っていなければ問題ないのかなと個人的には思います。

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17214/0e519edc-6de9-0bda-e538-d35e4ac332a4.gif)

こうしてPull Requestを作ると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17214/eac8a1f4-a446-610d-357d-d490438fad98.png)

うまく行った :exclamation:

### 惜しいところ

... と言いたいところですが、よく見ると残念ながら元のPull Request Templateが二重に入ってしまいます :sob: 
こちらはPRを作成するときにクエリパラメータで `template=null` のような無効なテンプレート指定をすると弾くこともできますが、ひとまずは手動でコメントを消しています。

ローカルでPull Requestを書き上げた方は、ぜひやってみてください :exclamation: 

# 参考資料

- [https://git-scm.com/docs/git-commit/2.10.5](https://git-scm.com/docs/git-commit/2.10.5)
- [https://git-scm.com/book/ja/v2/Git-のカスタマイズ-Git-の設定](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA-Git-%E3%81%AE%E8%A8%AD%E5%AE%9A)
- [https://qiita.com/suin/items/f6d722d20fc6af9b7108](https://qiita.com/suin/items/f6d722d20fc6af9b7108)