😸
リポジトリを綺麗に管理 ghq+fzf
はじめに
開発者として複数のGitリポジトリを扱う際、効率的な管理方法が求められます。本記事では、GitHub CLI(gh)、ghq、fzfを組み合わせた強力なリポジトリ管理ワークフローを紹介します。
この組み合わせにより、以下のことが可能になります:
- リポジトリの一元管理
- 高速なリポジトリ検索と移動
- インタラクティブなリポジトリ選択
- 危険な操作も安全に実行
必要なツール
ghq
Gitリポジトリを統一された場所で管理するツール。リポジトリを~/ghq/github.com/owner/repoのような構造で整理します。
GitHub CLI (gh)
GitHubのAPIを使用してリポジトリ情報を取得したり、操作を実行できるコマンドラインツール。
fzf
インタラクティブなファジーファインダー。リストから項目を選択する際の強力なUIを提供します。
Installation
必要なツールをインストールします。
Ubuntu/Debian
sudo apt install ghq gh fzf
macOS
brew install ghq gh fzf
Arch Linux
sudo pacman -S ghq github-cli fzf
基本的な使用方法
1. リポジトリの一覧表示と選択
GitHubのリポジトリ一覧を取得し、fzfで選択できます:
gh api --paginate /user/repos --jq '.[].full_name' | fzf
このコマンドは以下の処理を行います:
-
gh api --paginate /user/repos:GitHub APIからユーザーのリポジトリ一覧を取得 -
--jq '.[].full_name':JSON形式の結果からowner/repo形式のリポジトリ名を抽出 -
| fzf:リストをfzfに渡してインタラクティブに選択
2. リポジトリのクローンと移動
ghqを使用してリポジトリをクローンし、移動する:
# リポジトリをクローン
ghq get https://github.com/owner/repo
# ghqで管理されているリポジトリに移動
cd $(ghq root)/github.com/owner/repo
# またはghqのlistとfzfを組み合わせて選択
cd $(ghq root)/$(ghq list | fzf)
3. 実用的なワークフロー
以下のような組み合わせが効果的です:
# 自分のリポジトリから選択してクローン
repo=$(gh api --paginate /user/repos --jq '.[].clone_url' | fzf)
ghq get $repo
# クローン済みリポジトリから選択して移動
cd $(ghq root)/$(ghq list | fzf)
高度な使用例
リポジトリの削除(危険操作)
⚠️ 注意: このコマンドは実際にリポジトリを削除します。実行前に必ず確認してください。
gh repo delete $(gh api --paginate /user/repos --jq '.[].full_name' | fzf)
エイリアスの設定
よく使用するコマンドはエイリアスとして設定しておくと便利です:
# ~/.bashrc または ~/.zshrc に追加
alias ghr="gh api --paginate /user/repos --jq '.[].full_name' | fzf"
alias ghq-cd="cd \$(ghq root)/\$(ghq list | fzf)"
リポジトリ管理ツール repo()
repo() {
local action="${1:-list}"
case "$action" in
"list"|"l")
# List all repositories with fzf selection
local selected_repo
selected_repo=$(ghq list | fzf --height=50% --border --preview="echo {}" --preview-window=down:3:wrap)
if [[ -n "$selected_repo" ]]; then
echo "Selected: $selected_repo"
echo "Path: $(ghq root)/$selected_repo"
fi
;;
"cd"|"c")
# Change directory to selected repository
local selected_repo
selected_repo=$(ghq list | fzf --height=50% --border --preview="echo {}" --preview-window=down:3:wrap)
if [[ -n "$selected_repo" ]]; then
cd "$(ghq root)/$selected_repo" || return 1
fi
;;
"remove"|"rm"|"r")
# Remove selected repository
local selected_repo
selected_repo=$(ghq list | fzf --height=50% --border --preview="echo {}" --preview-window=down:3:wrap --prompt="Select repository to remove: ")
if [[ -n "$selected_repo" ]]; then
echo "Are you sure you want to remove $selected_repo? [y/N]"
read -r confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
rm -rf "$(ghq root)/$selected_repo"
echo "Removed: $selected_repo"
else
echo "Cancelled"
fi
fi
;;
"get"|"g")
# Clone/get a new repository
if [[ -z "$2" ]]; then
# Interactive mode: show remote repositories via gh + fzf
local selected_repo
selected_repo=$(gh repo list --limit 100 --json nameWithOwner --jq '.[].nameWithOwner' | fzf --height=50% --border --preview="gh repo view {} --json description,url,pushedAt --template '{{.description}}\n{{.url}}\nLast updated: {{.pushedAt}}'" --preview-window=down:5:wrap --prompt="Select repository to clone: ")
if [[ -n "$selected_repo" ]]; then
ghq get "github.com/$selected_repo"
fi
else
ghq get "$2"
fi
;;
"create"|"new"|"n")
# Create a new repository directory
if [[ -z "$2" ]]; then
echo "Usage: repo create <repository_path>"
echo "Example: repo create github.com/user/new-repo"
return 1
fi
local repo_path="$(ghq root)/$2"
mkdir -p "$repo_path"
cd "$repo_path" || return 1
git init
echo "Created and initialized: $2"
;;
"open"|"o")
# Open repository in editor (default: code)
local editor="${2:-code}"
local selected_repo
selected_repo=$(ghq list | fzf --height=50% --border --preview="echo {}" --preview-window=down:3:wrap)
if [[ -n "$selected_repo" ]]; then
local repo_path="$(ghq root)/$selected_repo"
if command -v "$editor" > /dev/null; then
"$editor" "$repo_path"
else
echo "Editor '$editor' not found. Trying fallback editors..."
if command -v code > /dev/null; then
code "$repo_path"
elif command -v vim > /dev/null; then
vim "$repo_path"
else
echo "No suitable editor found (code, vim)"
fi
fi
fi
;;
"help"|"h"|*)
# Show help
cat << 'EOF'
Repository management with ghq and fzf
Usage: repo <command> [args]
Commands:
list, l List repositories with fzf selection
cd, c Change directory to selected repository
remove, rm, r Remove selected repository (with confirmation)
get, g [url] Clone repository (interactive if no url)
create, new, n Create and initialize a new repository
open, o [editor] Open repository in editor (default: code)
help, h Show this help message
Examples:
repo # List repositories
repo cd # Change to selected repository
repo get # Interactive repository selection
repo get github.com/user/repo
repo create github.com/user/new-repo
repo remove # Remove selected repository
repo open # Open repository in code (default)
repo open vim # Open repository in vim
repo open nvim # Open repository in neovim
Requirements: ghq, fzf, git, gh (for interactive get)
EOF
;;
esac
}
まとめ
gh、ghq、fzfを組み合わせることで、以下のメリットが得られます:
- 統一された管理: ghqによるリポジトリの一元管理
- 高速な検索: fzfによるインタラクティブな選択
- 効率的な操作: GitHub APIとの連携による豊富な機能
- 安全な実行: 危険な操作も選択ベースで実行可能
このワークフローを活用することで、複数のリポジトリを効率的に管理し、開発生産性を向上させることができます。
参考情報

Discussion