Skip to main content

git blame tells you who. git-why tells you why — explains code from local git history, offline or with AI.

Project description

git-why

CI PyPI Stars Python MIT License PRs welcome

git blame tells you who broke it. git-why tells you why it's there in the first place.

It's 11pm. You've found a six-line guard clause that looks paranoid, maybe even wrong. git blame says Dave wrote it three years ago. Dave doesn't work here anymore. Do you delete it and hope, or burn twenty minutes in git log -p praying the commit message isn't just "fix"?

git-why does that archaeology for you — in under a second, completely offline, no API key, no setup beyond pip install.

git-why src/auth.py:42

git-why demo

It reads the actual commits and diffs around that line and reconstructs the story nobody wrote down anywhere else — or hands the same context to Claude/GPT/Gemini/Ollama/OpenRouter if you want a richer, AI-narrated version.

If this saves you a Slack message to a teammate who left the company two years ago, consider starring it — it helps other people stumbling through the same archaeology find this instead of reinventing it.

Install

pip install git-why

Or with an AI provider extra:

pip install "git-why[claude]"    # Anthropic Claude
pip install "git-why[openai]"    # OpenAI GPT
pip install "git-why[gemini]"    # Google Gemini
pip install "git-why[all]"       # all providers

Quick Start

git-why src/auth.py
git-why src/auth.py:42
git-why src/auth.py:42-60
git-why src/auth.py:42 --depth 30
git-why src/auth.py:42 --context 15
git-why src/auth.py:42 --verbose
git-why src/auth.py:42 --provider offline

Targets use FILE, FILE:LINE, or FILE:START-END. See the demo above for what the output actually looks like.

Offline And Free Mode

Offline mode is always available:

git-why src/auth.py:42 --provider offline

It reads the current file, runs local git commands, summarizes commit messages and diffs, and produces a non-AI markdown explanation. It does not need an API key and does not make internet calls.

The default provider is auto. Auto tries configured AI providers first and always falls back to offline.

Provider Setup

Provider order in auto mode:

  1. Claude when ANTHROPIC_API_KEY exists and anthropic is installed
  2. OpenAI when OPENAI_API_KEY exists and openai is installed
  3. Gemini when GEMINI_API_KEY exists and google-genai is installed
  4. OpenRouter when OPENROUTER_API_KEY exists
  5. Ollama when local Ollama is running
  6. Offline

Claude:

pip install "git-why[claude]"
set ANTHROPIC_API_KEY=your-key
git-why src/auth.py:42 --provider claude

OpenAI:

pip install "git-why[openai]"
set OPENAI_API_KEY=your-key
git-why src/auth.py:42 --provider openai

Gemini:

pip install "git-why[gemini]"
set GEMINI_API_KEY=your-key
git-why src/auth.py:42 --provider gemini

OpenRouter:

set OPENROUTER_API_KEY=your-key
git-why src/auth.py:42 --provider openrouter

Ollama:

ollama serve
ollama pull qwen2.5-coder
git-why src/auth.py:42 --provider ollama

PowerShell examples use set for brevity. Use your shell's normal environment variable syntax if needed.

Models

Override the model with --model:

git-why src/auth.py:42 --provider openai --model gpt-5.4-mini
git-why src/auth.py:42 --provider ollama --model qwen2.5-coder

Default models:

Provider Default model
Claude claude-sonnet-4-6
OpenAI gpt-5.4-mini
Gemini gemini-3.5-flash
OpenRouter openrouter/free
Ollama qwen2.5-coder

Model names change over time. Defaults are centralized in git_why/ai/defaults.py. If a model fails, pass --model.

Windows PATH Note

On Windows, pip install -e . may install git-why.exe into a Scripts directory that is not on PATH, for example:

%LOCALAPPDATA%\Programs\Python\Python313\Scripts

Add that Scripts directory to PATH, or run the script with its full path.

Examples

Explain a whole file:

git-why src/auth.py

Explain one line:

git-why src/auth.py:42 --provider offline

Explain a range with more history:

git-why src/auth.py:42-60 --depth 30

Show raw git context:

git-why src/auth.py:42 --verbose

Development

pip install -e ".[dev]"
python -m pytest

Limitations

  • Offline explanations are heuristic and based only on local git history.
  • Deleted or renamed files depend on what git can resolve from the current working tree.
  • Whole-file mode caps the displayed current code preview.
  • Binary files are detected and shown as a placeholder rather than raw bytes; commit history still comes from git log, but line-level git blame is skipped since line numbers aren't meaningful for binary content.
  • AI providers require their respective SDKs, keys, or local services only when explicitly selected or available in auto.

Roadmap

  • Publish to PyPI.
  • Add CI for tests and packaging checks.
  • Improve provider response parsing and error reporting.
  • Add more git-history context, such as issue or PR links when present in commit messages.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

git_why-0.1.0.tar.gz (19.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

git_why-0.1.0-py3-none-any.whl (19.6 kB view details)

Uploaded Python 3

File details

Details for the file git_why-0.1.0.tar.gz.

File metadata

  • Download URL: git_why-0.1.0.tar.gz
  • Upload date:
  • Size: 19.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for git_why-0.1.0.tar.gz
Algorithm Hash digest
SHA256 42a1a5223966db34f2f2177a6a410b0c184154be2c409580844b5b7fd2e746fa
MD5 ac04951a7ea8ab94dc20ca0b0a98df1c
BLAKE2b-256 8b8ae8041d786447fe7d0f386bd00bf88aabcd134f8557a3827237d8fde86b08

See more details on using hashes here.

File details

Details for the file git_why-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: git_why-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 19.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for git_why-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2e77f64e663af2eb0fa1b0c04557d2c9aed8da8ccbe4fa9b4a0119979e248662
MD5 27091651dd925f67572f038d0842288f
BLAKE2b-256 4cd64ad437503a6af21d7ac25286fe4b45c41ccc2a8767d90a4820861bf9b6e0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page