Interactive Git branch browser with fzf integration and GitHub PR status
Project description
git-branches
An interactive Git branch browser powered by fzf, with rich previews for GitHub PRs and CI status. It’s fast, keyboard-first, and designed for day-to-day workflows: jump to branches, spin up local tracking from remotes, open the PR in your browser, or prune branches in bulk.
TL;DR ⚡️
# Install (Homebrew tap)
brew tap chmouel/git-branches https://github.com/chmouel/git-branches
brew install --HEAD chmouel/git-branches/git-branches
# Browse local branches (preview on top)
git-branches
# Browse remote branches (pick a remote)
git-branches -r
# Show pushed-status icons for local branches
git-branches -s # add -S to show all
# Show GitHub Actions status (fetch over network)
git-branches --checks
Highlights
- fzf-native UX: reverse list, previews, key bindings, multi-select for deletes.
- Rich preview: PR status (Open/Draft/Merged/Closed), OSC-8 link to the PR, CI combined status, and the last 10 commits with colors.
- GitHub awareness: shows whether a local branch exists on the remote (
-s) and the CI status for the PR head commit. - One-keystroke actions: checkout, open PR (
ctrl-o), delete quickly (alt-k).
Requirements
- git and fzf on PATH
- Python 3.12+ (uv-managed)
- Optional:
GITHUB_TOKEN(improves rate limits and enables private repos) - Optional: a Nerd Font for icons (fallback text is still readable)
Installation 🍺
-
Local dev via uv
make installmake run(or pass flags withARGS="...")
-
System-wide (optional)
- From this directory:
uv tool install . - Then invoke the console script:
git-branches
- From this directory:
Homebrew (Tap)
You can install via a Homebrew tap that ships a Formula for git-branches.
Option A — tap this repo directly (HEAD installs from the main branch):
brew tap chmouel/git-branches https://github.com/chmouel/git-branches
brew install --HEAD chmouel/git-branches/git-branches
Option B — local developer tap (no remote push needed):
TAP="${USER}/git-branches-dev"
brew tap-new "$TAP"
TAP_DIR="$(brew --repo "$TAP")"
mkdir -p "$TAP_DIR/Formula"
cp Formula/git-branches.rb "$TAP_DIR/Formula/"
brew install --HEAD "$TAP/git-branches"
Or use the Makefile helper (does the same steps for you):
make brew-local
# or pick a custom tap name
make brew-local TAP="${USER}/git-branches-dev"
Option C — copy Formula/git-branches.rb into your own GitHub tap repo (recommended for teams) and install:
brew tap <org>/<tap>
brew install --HEAD <org>/<tap>/git-branches
Notes:
- The Formula uses Homebrew’s Python virtualenv and installs
git-branchesalong with its Python dependencies. - Runtime dependencies
gitandfzfare declared and installed by Homebrew. --HEADinstalls from the main branch. For a pinned/stable release, update the Formulaurlandsha256to a tagged tarball.
Quickstart 🚀
- Browse and checkout local branches:
git-branches
- Browse remotes and checkout (creates tracking branch if needed):
git-branches -r(select remote interactively)git-branches -R origin
- Deletion workflows:
git-branches -d(delete local; multi-select)git-branches -D -R origin(delete remote)
- See if local branches exist on the remote:
git-branches -s(shows pushed status with default limit of 10)git-branches -s -S(disable default limit)
Command-line options 🧭
-r: Browse remote branches (choose remote via fzf)-R <remote>: Browse a specific remote (e.g., origin)-d: Delete local branches (multi-select)-D: Delete remote branches (multi-select)-s: Show pushed status for local branches (GitHub API)-n <N>: Limit to first N branches-S: With-s, disable default limit (show all)-C: Disable colors-l: List-only mode (no checkout)--refresh: Force refresh of PR cache (ignore stale cache and ETag)--checks: Fetch and show GitHub Actions status (preview and a small indicator in rows). Without this flag, cached results (if available) are still displayed, but no network calls are made for checks.
Icons legend 🔤
- PR state:
- Open:
(green) - Draft:
(yellow) - Merged:
(magenta) - Closed:
(red)
- Open:
- GitHub Actions:
- In progress:
(yellow) - Success:
(green) - Failed/Timed out:
(red) - Cancelled:
(red) - Skipped/Neutral:
(cyan)
- In progress:
Tip: Use a Nerd Font for best results. Without it, the text remains legible.
Key bindings (fzf)
ctrl-o: Open the PR for the highlighted ref in the default browseralt-k: Force-delete highlighted local branch (quick action)
Shell Completion 🔌
Supported shells and scripts under contrib/:
- Zsh:
_git-branches - Bash:
git-branches.bash - Fish:
git-branches.fish
Zsh
Add the contrib directory to your fpath in .zshrc and re-init completions:
fpath+=($PWD/contrib)
autoload -U compinit && compinit
Use the absolute path to your clone instead of $PWD in your dotfiles.
Bash
Source the completion script from your .bashrc or .bash_profile:
source /absolute/path/to/contrib/git-branches.bash
Fish
Copy or symlink the Fish completion to your user completions directory:
mkdir -p ~/.config/fish/completions
ln -sf /absolute/path/to/contrib/git-branches.fish ~/.config/fish/completions/git-branches.fish
Arch Linux (PKGBUILD / AUR-style)
This repository includes a PKGBUILD under aur/ for a -git style package (builds from HEAD).
- Build locally with makepkg (requires
base-devel):
cd aur
makepkg -sci --noconfirm
How it works
- Uses git for data (branch lists, recent commits) and fzf for the UI.
- Detects GitHub repository from the upstream of the current branch when possible, falling back to
originor the first remote. - For
-sand preview CI status, calls the GitHub API withAuthorization: Bearer $GITHUB_TOKENwhen set.
Performance and Caching ⚙️
To improve performance and reduce API calls, git-branches batches git metadata and PR queries and caches PR data locally.
- Git metadata: branches and last-commit info are fetched via a single
git for-each-refcall. - PR list: fetched via REST in one call (
/pulls?state=open&per_page=100) with ETag support; a small slice of recently closed PRs is also fetched to catch merges. - Disk cache:
~/.cache/git-branches/prs.jsonwithtimestamp,etag, and a{head.ref -> PR}map. Default TTL: 5 minutes.
Controls:
GIT_BRANCHES_OFFLINE=1: skip all GitHub API calls.GIT_BRANCHES_PREFETCH_DETAILS=1: batch GraphQL for labels/reviews/body to make previews instant.GIT_BRANCHES_NO_CACHE=1: ignore and do not write disk cache; do not use in-memory caches.--refreshorGIT_BRANCHES_REFRESH=1: ignore existing cache and ETag this run, then write a fresh cache.
Environment Variables 🔧
GIT_BRANCHES_OFFLINE=1: Run fully offline (no GitHub requests).GIT_BRANCHES_NO_CACHE=1: Bypass disk/memory caching and ETag.GIT_BRANCHES_REFRESH=1: Force refresh of caches for this run.GIT_BRANCHES_PREFETCH_DETAILS=1: Prefetch PR details (GraphQL batches).GIT_BRANCHES_SHOW_CHECKS=1: Allow fetching Actions status (same as--checks). If unset, cached checks are still displayed; no fetches.GIT_BRANCHES_NO_PROGRESS=1: Disable spinners/progress indicators.
Troubleshooting 🛠️
-
“fzf not found”: Install fzf and ensure it’s on PATH (
brew install fzf,apt install fzf, etc.). -
“Not in a git repository”: Run within a git repo.
-
No icons? Install a Nerd Font and configure your terminal to use it.
-
Low API rate limit? Set
GITHUB_TOKEN(a classic or fine-grained PAT works). -
Homebrew says “formula not in a tap”: create a local tap and install:
TAP="${USER}/git-branches-dev" brew tap-new "$TAP" TAP_DIR="$(brew --repo "$TAP")" mkdir -p "$TAP_DIR/Formula" cp Formula/git-branches.rb "$TAP_DIR/Formula/" brew install --HEAD "$TAP/git-branches"
Development 🧪
- Lint:
make lint(auto-fix:make fix) - Tests:
make test(pytest) - Dev loop:
make dev(ruff fix → pytest → ruff format) - Format:
make format(ruff)
License
See the repository’s LICENSE file.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file git_branches-0.1.1.tar.gz.
File metadata
- Download URL: git_branches-0.1.1.tar.gz
- Upload date:
- Size: 32.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
827990dd17ccdc53c2d88efd469cdf2b72102b2c29942cb5b7294e0dca83b4ea
|
|
| MD5 |
410789c6ef8dfc7815649c4c731557e9
|
|
| BLAKE2b-256 |
f2fba18ec8e7f582ce6284e9d1eed3956cc874bb42db361674a1c448e4be0959
|
File details
Details for the file git_branches-0.1.1-py3-none-any.whl.
File metadata
- Download URL: git_branches-0.1.1-py3-none-any.whl
- Upload date:
- Size: 28.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3fa4a1d2e696c54f5cca2fb6a244ac756ec51e193af30a4beb2cc21dac5cd8b3
|
|
| MD5 |
5723cd75ce6ccafb38b5e6eb52e498f6
|
|
| BLAKE2b-256 |
c94080aa5aaec262a792c5019bb4113cab9c614245489ec113435aa0b6a36103
|