GitHub CLI + fzf でGitHubライフがとても快適になった話

# はじめに
みなさん、ghコマンド使っていますか？
[GitHub CLI](https://cli.github.com/)をインストールすると使えるようになるコマンドで、CLI上からGitHubに対して操作をすることができます。

私は「わざわざツールインストールしてまでCLIからGitHubに対して操作しなくても、ブラウザでできるじゃん」と思っていましたが、試しに使ってみたら想像以上にghコマンドを使ったGitHubが快適だったので、それを記事に書きます。
また、コマンドラインファジーファインダーの[fzf](https://github.com/junegunn/fzf)と組み合わせるとさらに快適になったので、そちらについても書きます。

# 環境情報
実装して挙動確認した環境は以下です。

|対象  |バージョン  |
|---|---|
|Mac  |Sequoia 15.1.1（24B91）  |
|gh  |2.63.2 (2024-12-05)  |
|fzf  |0.56.3  |

# 初期設定
もう記事を書かれている方がいるので、そちらを参照ください。

[GitHub CLIで始める快適GitHub生活](https://qiita.com/ryo2132/items/2a29dd7b1627af064d7b#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)

# よく使うコマンドの紹介
## 作業しているリポジトリのGitHubページ表示
```sh
gh browse
```

今いるディレクトリのリポジトリに対応するGitHubリポジトリのページを表示してくれます。
GitHubでリポジトリを見て、コミットやリリース、Github Actionsなどの状況を見たいことがあると思いますが、わざわざブラウザを開いてブックマークからGitHubに飛んで...をしなくても一瞬で開けます。
オプションを指定することでブランチやコミットを指定したり、releasesやsettingsのページに飛ぶこともできます。

```sh
FLAGS
  -b, --branch string            Select another branch by passing in the branch name
  -c, --commit string[="last"]   Select another commit by passing in the commit SHA, default is the last commit
  -n, --no-browser               Print destination URL instead of opening the browser
  -p, --projects                 Open repository projects
  -r, --releases                 Open repository releases
  -R, --repo [HOST/]OWNER/REPO   Select another repository using the [HOST/]OWNER/REPO format
  -s, --settings                 Open repository settings
  -w, --wiki                     Open repository wiki
```

## 作業しているブランチのプルリクエストをGitHub上で作成
```sh
gh pr create --web
```

GitHubを使っているチームではGitHubのプルリクエストでレビュー依頼を出すことが多いと思いますが、地味にプルリクを作るのって面倒です。
プルリクエストのページを開いて、今のブランチ名を入力して、...の手順をこのコマンドで省くことができます。
フラグをつけることでアサイニーやレビュワー、ラベル、マージ先ブランチなども指定することができます。

```sh
FLAGS
  -a, --assignee login       Assign people by their login. Use "@me" to self-assign.
  -B, --base branch          The branch into which you want your code merged
  -b, --body string          Body for the pull request
  -F, --body-file file       Read body text from file (use "-" to read from standard input)
  -d, --draft                Mark pull request as a draft
      --dry-run              Print details instead of creating the PR. May still push git changes.
  -e, --editor               Skip prompts and open the text editor to write the title and body in. The first line is the title and the remaining text is the body.
  -f, --fill                 Use commit info for title and body
      --fill-first           Use first commit info for title and body
      --fill-verbose         Use commits msg+body for description
  -H, --head branch          The branch that contains commits for your pull request (default [current branch])
  -l, --label name           Add labels by name
  -m, --milestone name       Add the pull request to a milestone by name
      --no-maintainer-edit   Disable maintainer's ability to modify pull request
  -p, --project title        Add the pull request to projects by title
      --recover string       Recover input from a failed run of create
  -r, --reviewer handle      Request reviews from people or teams by their handle
  -T, --template file        Template file to use as starting body text
  -t, --title string         Title for the pull request
  -w, --web                  Open the web browser to create a pull request
```

## 作業中のブランチに対応するプルリクエスト表示
```sh
gh pr view --web
```

自分が出しているプルリクエストが多い場合、地味に今作業しているブランチに対応するプルリクエストを探すのって面倒ですよね。
このコマンドを打つと作業しているブランチに対応するプルリクエストを表示してくれます。

## プルリクエスト一覧を表示
```sh
gh pr list
```

プルリクエストの一覧を表示します。
CLI上でプルリクの番号、タイトル、マージ元ブランチ、プルリクの作成日が一覧でみれます。

自分がよく使うオプションは以下です。
```sh
# デフォルトは30件表示でそれ以上は省略されてしまうので、100件表示にする
-L 100

# 自分のプルリクに絞る（他の人にもできます）
--author @me

# ブラウザで開く
--web
```

他にもアサイニーやマージ先ブランチ、ラベルなどでフィルターできます。
```sh
FLAGS
      --app string        Filter by GitHub App author
  -a, --assignee string   Filter by assignee
  -A, --author string     Filter by author
  -B, --base string       Filter by base branch
  -d, --draft             Filter by draft state
  -H, --head string       Filter by head branch
  -q, --jq expression     Filter JSON output using a jq expression
      --json fields       Output JSON with the specified fields
  -l, --label strings     Filter by label
  -L, --limit int         Maximum number of items to fetch (default 30)
  -S, --search query      Search pull requests with query
  -s, --state string      Filter by state: {open|closed|merged|all} (default "open")
  -t, --template string   Format JSON output using a Go template; see "gh help formatting"
  -w, --web               List pull requests in the web browser
```

## プルリクエストのブランチにcheckout
```sh
gh co #(プルリク番号)
```
プルリクエストレビューの際にそのブランチへ移動して手元でコードを表示しながら確認したいことがありますが、ブランチ名をコピーして、checkoutして、でちょっと面倒です。
このコマンドを使うとプルリク番号だけでそのプルリクにcheckoutしてくれるので、urlからプルリク番号を見て打つだけでよいです。
さらに、自動で最新の状態までブランチを更新してくれます。

# fzfと組み合わせるとさらに便利に！
コマンドラインファジーファインダーのfzf（peco, percolなどでもよいです）と組み合わせるとさらに便利になります！

## プルリク一覧を表示し、そこからプルリクを選択して開く
```sh
gh pr list | fzf | awk '{print $1}' | xargs gh pr view --web
```
プルリクをスムーズに見られるようにするコマンドです。
`gh pr list` にオプションを追加することで、自分の作ったプルリク一覧にしたり、Aさんがアサイニーになっているものなどに絞ることもできます。

## プルリク一覧を表示し、プルリクを選択してcheckoutする
```sh
gh pr list | fzf | awk '{print $1}' | xargs gh co
```

プルリクのブランチにスムーズに遷移できるようにするコマンドです。
レビュー時に重宝します。
またプルリクが出ているブランチ間であれば、タイトルも見ながらフィルターして選択できるのでブランチの移動ミスが減ります（自動でリモートブランチの最新に更新もしてくれます）。

## マージ先ブランチを指定してプルリクエストを作成
プルリクエストを作る際、マージ先ブランチの入力もマージ元ブランチの入力もしたくないと思って作ったコマンドです。
ブランチ名が長い場合、GitHub上のUIだと省略されちゃって見辛いことがあるのですよね。

まず、前準備として以下のような作業中リポジトリのブランチ一覧をfzfでフィルターする関数を定義します。

```sh
function branch_list(){
  git branch -a --sort=-committerdate --color \
    | fzf --preview "echo {} | sed -e 's/\*//' | awk '{print \$1}' | xargs git log --color --graph --decorate --abbrev-commit --format=format:'%C(blue)%h%C(reset) - %C(green)(%ar)%C(reset)%C(yellow)%d%C(reset)\n  %C(white)%s%C(reset) %C(dim white)- %an%C(reset)'" \
    | xargs echo | sed -e 's/\*//' | awk '{print $1} | sed -e 's/remotes\/origin\///'
}
```

上記を使って、以下のようにするとマージ先ブランチをfzfでフィルター選択して、作業中ブランチのプルリクエストを作成することができます。
```sh
branch_list | xargs gh pr create --web --base
```

# 終わりに
私が使っていて便利と感じたghコマンドの使い方を紹介しましたが、いかがでしたか。
私はGitHubを基本毎日使うので、ghコマンドを使うようになって小さいですが作業時間が短縮されましたし、煩わしい作業が減りました。
導入や設定も難しくなくて簡単なので、興味が湧いたらぜひ使ってみてください！
また、こんな使い方も便利だよという使い方があればぜひ教えてください。