ShellScript
Git
GitHub
hub

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

TL;DR

  • hub コマンドでプルリクエストをコマンドラインから作成する方法を紹介します
  • 安定版ではなく pre 版を使うと、 .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 2.3.0-pre10
    • :warning: ここで使うのは pre 版です

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

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

hub コマンドのおさらい

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

例えば、

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

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

なぜ pre版の hub を使う?

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

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>]

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.mdPULL_REQUEST_TEMPLATE.md といったファイルを作っておくと、GitHubのIssueやPullRequestを作成した時にテンプレートとして事前にファイルの中身を入力した状態となります。
例えば自社3では、次のようなテンプレートを用意しています。

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

# 概要

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 を活用できない

hub pull-request

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

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

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

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

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

image.png

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

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

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

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

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

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

image.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

git alias を作る

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

git config --global alias.prpr '!hub pull-request -F .github/PULL_REQUEST_TEMPLATE.md --edit -a yasuhiroki'

といった風に git prpr で PullRequest を作るように設定しています。

余談

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

alias 娘の名前=git

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