GitHubのコマンドラインツール hub でプルリクエストを効率よく作る

# TL;DR

- `hub` コマンドでプルリクエストをコマンドラインから作成する方法を紹介します
- ~~安定版ではなく `pre` 版を使うと~~ 2.3.0以降を使うと、 `.github/PULL_REQUEST_TEMPLATE.md` をベースに編集できるので便利です
    - コマンド例: `hub pull-request -F .github/PULL_REQUEST_TEMPLATE.md --edit`
- `#` は Markdown の見出し文字ですが、`git`コミットメッセージのコメントアウトでもあり被ってしまうので `git config --global core.commentchar ";"` か `git config --global core.commentchar "auto"` を設定しておきましょう

# 筆者の環境

- MacBook Pro High Sierra
- git 2.17.0
- [hub](https://github.com/github/hub/) 2.3.0-pre10
  - :warning: 本記事で使っていたのは `pre` 版です
  - すでに 2.3.0 はリリースされているので、それ以降なら動くと思います

# hub 2.3.0-pre10 をインストールする

pre版なので `brew` ではなく次のどちらかの方法でインストールしてください

- https://github.com/github/hub/releases からダウンロードする
- `go get github.com/github/hub` する

# hub コマンドのおさらい

`hub` コマンドは GitHub が作っている GitHub用CLIツールです。
`git` コマンドを拡張し、GitHub固有の機能にアクセスできるようになります。

例えば、

- `git clone github/hub` などとリモートリポジトリURLを省略して `clone` できる
- `git compare develop..feature` とするとブラウザでGitHubのcompareページを開く
- `git pull-request` でPullRequestを作成できる

といった事ができるようになります。[^1]
[^1]: 詳しくはマニュアル https://hub.github.com/hub.1.html
 をご覧ください 

なお、本項では `hub` コマンドによる操作は、既存の `git` コマンドでは使えないコマンドであると分かりやすくするため `hub` で始めるものとします。

# なぜ pre版の `hub` を使う？

`pull-request` コマンドの機能がかなり違います。
例えば `--help` の出力を見てみると、 pre版の方が安定版の1.5倍くらいオプションの数が多いです。

```bash:2.2.9
$ hub  pull-request --help
usage: git pull-request [-f] [-m <MESSAGE>|-F <FILE>|-i <ISSUE>|<ISSUE-URL>] [-o] [-b <BASE>] [-h <HEAD>]

```

```bash:2.3.0-pre10版
$ hub pull-request --help
Usage: hub pull-request [-focp] [-b <BASE>] [-h <HEAD>] [-r <REVIEWERS> ] [-a <ASSIGNEES>] [-M <MILESTONE>] [-l <LABELS>]
```

そもそも安定版がリリースされたのは 2016/10/04 と古いため、PullRequestのレビューワー指定オプションが無いなど、GitHubの追加機能に対応しきれていません。
これだけでもpre版を利用する理由になりますが、特に私が必要とした機能は `.github/PULL_REQUEST_TEMPLATE.md` をベースに `edit` できるようになったことです。

## `.github/PULL_REQUEST_TEMPLATE.md` とは

2016/02 に GitHub に追加された機能[^2] で、リポジトリルートに `.github` というディレクトリを作り、 `ISSUE_TEMPLATE.md` や `PULL_REQUEST_TEMPLATE.md` といったファイルを作っておくと、GitHubのIssueやPullRequestを作成した時にテンプレートとして事前にファイルの中身を入力した状態となります。
[^2]: https://blog.github.com/2016-02-17-issue-and-pull-request-templates/

例えば自社[^3]では、次のようなテンプレートを用意しています。
[^3]: [A10 Lab Inc.](https://a10lab.com/)

### Androidアプリ用リポジトリの `PULL_REQUEST_TEMPLATE.md` の例

```markdown
# 概要

Story: [Storyチケット番号](StoryチケットURL)

# 修正内容

# 動作確認

- [ ] Xperia A (4.2.2)
- [ ] Xperia Z5 (6.0)
- [ ] Nexus (7.1.1)
- [ ] Xperia XZ Premium (8.0.0)

# レビューして欲しいポイント

- XXXについてチェックして欲しい
- YYYというメソッド名で良いのか悩んでいる

# 補足
```

# `hub` コマンドでPullRequestを作る

## 安定版(2.2.9) `hub` では `PULL_REQUEST_TEMPLATE.md` を活用できない

```bash
hub pull-request
```

とすれば、カレントブランチからデフォルトブランチに対してPullRequestを作ることができます。コマンド実行後にエディターが立ち上がり、PullRequestの説明を書いて保存すればOKです。

しかし、これでは `PULL_REQUEST_TEMPLATE.md`が使えません。立ち上がったエディターに、わざわざ `PULL_REQUEST_TEMPLATE.md` の内容をコピペして編集する必要があります。これは面倒ですね。エディターが立ち上がった時点で `PULL_REQUEST_TEMPLATE.md` の内容が書いてあって欲しいものです。

しかし、安定版の `2.2.9` では **テンプレートそのままの内容でしかPullRequestを作ることができません** 。

```bash:2.2.9でPULL_REQUEST_TEMPLATE.mdを使うには
hub pull-request -F .github/PULL_REQUEST_TEMPLATE.md
```

このように `-F` オプションでPullRequestの内容をファイルから取得させれば良いのですが、これではエディターが立ち上がらず、 `PULL_REQUEST_TEMPLATE.md` の内容そのままでPullRequestが作られてしまうのです。

おまけに一行目はPullRequestのタイトルとして扱われるので `# 概要` という非常にダサいタイトルのPullRequestができてしまいます。

### :angel: 非常にダサいPullRequestのタイトル

![image.png](https://qiita-image-store.s3.amazonaws.com/0/27201/51b232f5-c98a-21e2-84b2-de1d900cbba3.png)

### :angel: 非常にダサいタイトル変更履歴

![image.png](https://qiita-image-store.s3.amazonaws.com/0/27201/512ee9a0-f0c1-1327-bff1-f93dcd19efa1.png)

## `2.3.0-pre10` の `--edit` オプションを活用する

`hub 2.3.0-pre10` だと `--edit` オプションが使えます。

```bash
hub pull-request -F .github/PULL_REQUEST_TEMPLATE.md --edit
```

とすると `.github/PULL_REQUEST_TEMPLATE.md` の内容が読み込まれた状態でエディターが立ち上がり、内容を変更してから保存することで、修正後の内容でPullRequestを作ることができます。

これで良かった良かった... **とはいきません** :upside_down:

### :angel: なんだか思ってたのと違うPullRequest

![image.png](https://qiita-image-store.s3.amazonaws.com/0/27201/b22074fa-05a6-a52e-5639-d483b2771535.png)

見出し文字が全て消えていることにお気づきでしょうか？

## `git config core.commentchar` でコメントアウトの文字を変更する

そう、Gitのコメントアウトは shell と同じく `#` を使うのです。
そのため Markdown で見出しを記述したくてもコメントアウト扱いにされてしまい、プルリクエストの本文から消えてしまったのです。

この git のコメントアウトに使用する文字は `git config core.commentchar` で変更できます。
私は `git config --global core.commentchar ";"` としています。 `;` は Vim Script のコメントアウト文字なので見慣れているのです。

しかし中には  git のコメントアウトは `#` である前提のツールもあるし、他の文字に変更するのは難しい、と考えるかたもいるでしょう。
`hub` のコミュニティでもその議論があり、そこで `git config core.commentchar auto` が設定されていたら、 hub pull-request -F で渡されたファイルに含まれていない記号を見つけて、それをコメントアウトのプレフィックスとして使う、という実装がされました。[^4]
[^4]: https://github.com/github/hub/pull/1660/

# git alias を作る

毎回 `hub pull-request -F .github/PULL_REQUEST_TEMPLATE.md --edit` などと長い文字を入力するのま面倒なので alias を登録しましょう。
例えば私は、

```bash
git config --global alias.prpr '!hub pull-request -F .github/PULL_REQUEST_TEMPLATE.md --edit -a yasuhiroki'
```
といった風に `git prpr` で PullRequest を作るように設定しています。

## 余談

なぜ `pr` ではなく `prpr` なのかは海より深く山より高い理由がありまして、
私は、

```bash
alias 娘の名前=git
```

という alias を設定して日々の仕事をしています。
時に、どうしようもなく娘を `prpr` したくなる時があるので、その欲求を満たすべく `娘の名前 prpr` とコマンドを入力しているのです。 `pr` ではダメな理由がそこにあります。