🧰

ghq + fzf で複数リポジトリ環境を快適にする(移動・pull・削除)

に公開

はじめに

複数の GitHub リポジトリを並行して触っていると、次のような困りごとが出がちです。

  • 目的のリポジトリに移動するまでが面倒
  • リポジトリが乱立する
  • どこに clone したか忘れる
  • 別リポジトリへの移動がめっちゃめんどくさい

この記事では、リポジトリ管理ツールの ghq と、対話型ファジーファインダーの fzf を組み合わせると、以下のようにターミナル上でGUI形式でリポジトリを選択させることができます。
さらに、そこから選択したリポジトリのディレクトリへ移動させたり、特定の処理を実行したりもできます。

複数のリポジトリ管理サービス、Organization、リポジトリを活用される方は特におすすめです。ではやっていきましょう。

インストール

試した環境

  • VS Code: 1.108.2
  • Ubuntu: 22.04

ghq のインストール

unzip のインストール

ghq のバイナリ(zip)を展開するため、まず unzip を入れます。

sudo apt update
sudo apt-get install unzip -y

which unzip
# /usr/bin/unzip

ghq のインストール(zip バイナリ)

GitHub Releases から ghq_linux_amd64.zip を取得し、展開したバイナリを /usr/local/bin/ に配置します。

# 例: ダウンロード済みの zip を展開
unzip ghq_linux_amd64.zip

# ghq を PATH の通った場所に配置
sudo mv ghq_linux_amd64/ghq /usr/local/bin/

# 動作確認
ghq --version
# ghq version 1.8.0 (rev:406c7dc)

# 後片付け(任意)
rm -rf ghq_linux_amd64 ghq_linux_amd64.zip

参考: ghq


fzf のインストール

Ubuntu では apt で導入できます。

sudo apt install fzf

which fzf
# /usr/bin/fzf

参考: fzf


実際に使ってみる

効果的に利用するための事前準備

ghq と fzf の役割はざっくり以下です。

  • ghq: ローカルにあるリポジトリの一覧取得・ルートディレクトリ配下のパス解決
  • fzf: ghqで取得したリポジトリを一覧化する UI の提供(プレビューも可能)

これらをシェルスクリプトとして組み合わせることで、ターミナル上で利用できる便利なコマンドを作り出すことができます。

まず、ghqコマンドでリポジトリの一覧を改めてクローンしておきます。
コマンドは以下の通りです。

ghq get <リモートリポジトリのURL.git>

このコマンドを実行すると、githubリポジトリの場合は ~/ghq/github.com配下に配置されます。

便利なコマンド一例(bash/zsh 関数)

ghqでリポジトリをローカルに整理して配置したうえで、コマンドを作っていきましょう。

以下は ~/.bashrc または ~/.zshrc に追記して使う想定です。
ちなみに、関数の名前は好きにカスタム可能ですので、自分の好みに合わせてカスタムしてみてください。

1) ghq & fzf でリポジトリに移動する(cd)

grg() {
  local selected dir

  # github.com/ を消して owner/repo のみ表示、プレビューあり
  selected=$(ghq list | sed 's|^github.com/||' \
    | fzf --height=40% --layout=reverse --border \
          --preview 'ls -la "$(ghq root)/github.com/{}"')

  # 何も選択されなかった場合は終了
  [ -n "$selected" ] || return

  # パス取得して移動
  dir=$(ghq list -p "github.com/$selected")
  [ -d "$dir" ] || return

  cd "$dir" || return
}

2) ghq & fzf で選択したリポジトリで git pull する

cd せずに git -C を使う形にしておくと、カレントディレクトリを汚しません。

gpl() {
  local selected dir

  selected=$(ghq list | sed 's|^github.com/||' \
    | fzf --height=40% --layout=reverse --border \
          --preview 'ls -la "$(ghq root)/github.com/{}"')

  [ -n "$selected" ] || return

  dir=$(ghq list -p "github.com/$selected")
  [ -d "$dir" ] || return

  echo "Pulling $selected..."
  git -C "$dir" pull
}

3) ghq & fzf で選択したリポジトリを削除(要注意)

この関数は ローカルディレクトリを rm -rf で削除します。
誤操作すると復元が大変なので、必ず確認プロンプトを入れてください。

gdl() {
  local selected dir answer

  selected=$(ghq list | sed 's|^github.com/||' \
    | fzf --height=40% --layout=reverse --border \
          --preview 'ls -la "$(ghq root)/github.com/{}"')

  [ -n "$selected" ] || return

  dir=$(ghq list -p "github.com/$selected")
  [ -d "$dir" ] || return

  echo "Delete $dir? (y/N): "
  read -r answer
  if [ "$answer" = "y" ] || [ "$answer" = "Y" ]; then
    rm -rf -- "$dir"
    echo "Deleted: $selected"
  else
    echo "Cancelled."
  fi
}

まとめ

  • ghq でローカルのリポジトリを一覧化・パス解決できるようにしておくと、リポジトリ数が増えても迷子になりにくい
  • fzf を組み合わせると、一覧から目的のリポジトリを素早く選んで、そのまま処理(移動/pull/削除などの処理)ができる

ぜひ、使ってみてください。

参考資料

Discussion