Back to blog
EngineeringDate unavailable· min read

When `python` Isn't Python: A Git Hook Story

A one-line fix that prevents pre-push hook failures on systems where `python` doesn't mean Python 3.

We shipped a one-line fix today that you probably won't notice—unless you were one of the developers whose pre-push hook was silently failing.

The Problem

Our pre-push git hook runs Python scripts to validate code before it leaves your machine. The hook was calling `python` directly—a command that's ambiguous on many systems. On macOS and many Linux distributions, `python` either points to Python 2.x (still!) or doesn't exist at all. Meanwhile, `python3` is reliably available and points to Python 3.x.

The result? Developers would install the hook, try to push, and get cryptic failures or silent skips. The hook would fail to run, validation wouldn't happen, and the safety net we built disappeared.

The Fix

Change `python` to `python3`. That's it. One token. The hook now explicitly resolves a Python 3 interpreter, which is the standard command across modern systems.

This isn't clever engineering. It's recognizing that the Python ecosystem made a deliberate choice: PEP 394 recommends that `python3` should be the stable, unambiguous way to invoke Python 3.x. We were ignoring that convention and paying for it in broken local flows.

Why It Matters

Developer experience lives in the margins. It's not the big features or architectural decisions—it's the git hook that works on the first try, the setup script that doesn't require a troubleshooting session, the environment that assumes your system is configured reasonably and adapts when it isn't.

This fix removes friction. Developers on macOS, Ubuntu, Fedora, or any modern Linux distribution can now install the pre-push hook and trust that it will run. The validation layer we built—type checking, linting, test execution—actually activates. The safety net is back.

The Hidden Cost

How many pushes happened without validation because the hook silently failed? We don't know. Git hooks fail quietly by design—they write to stderr, maybe, and then the push proceeds. There's no telemetry, no error reporting, no way to know how many developers thought the hook was working when it wasn't.

That's the hidden cost of environment assumptions. The code works on one machine—probably the original author's—and breaks elsewhere. The failure is silent, invisible, and only surfaces when someone notices and investigates.

What's Next

This fix is live. If you're running the pre-push hook and it was failing before, it should work now. If you haven't installed the hook yet, the setup instructions are in the repo README.

Longer term, we're looking at hook observability—ways to detect when hooks fail silently and surface that to developers or CI. Git doesn't make this easy, but the problem is real enough that we'll find a way.

We're also auditing other tooling for similar environment assumptions. Anywhere we call external commands—Python, Node, system utilities—we're checking that we're using the most portable, explicit form. One-line fixes compound.