← All posts

Who Am I?

July 2, 2026
gitproductivitydevtoolsopensource

The cognitive tax of Git identity management — and how I fixed it

I still ask myself this question before every commit: Who am I right now?

That hesitation. The finger pause. Not philosophy. Just Gut Git feeling.

I’ve pushed personal commits to client repos. I’ve also done the reverse — work identity on open-source PRs. Nothing broke immediately. But in regulated environments, that wrong name starts an audit conversation nobody wants to have.

After nearly two decades of this, I’ve realised the most expensive bugs aren’t in the code. They’re in the seams around it. Git identity is one of those seams. And almost nobody talks about it.


The Four Flavours of This Pain

Here’s the thing: I don’t work under a single identity anymore. Neither do you.

One hour I’m pushing to my company’s GitHub org. Next, I’m debugging a freelance client’s GitLab repo. Then I’m patching an open-source project I maintain. Each one expects a different email, a different SSH key, maybe a GPG signature if the org requires signed commits.

Git is brilliant at tracking changes. It’s terrible at tracking intent. It doesn’t know who I meant to be — it just uses whatever profile happened to be active last. That gap? That’s where the friction lives.

The wrong name on a commit. You write an hour of code, push, and someone pings you: “Hey, this came from your personal account.” Now you’re amending, force-pushing, and explaining yourself to someone who doesn’t care about Git — they just want the fix. The code was fine. The identity wasn’t.

The endless shuffle. git config user.email "work@company.com". Later: git config user.email "me@gmail.com". Each switch takes ten seconds. Over a year, that’s hours. And one forgotten switch undoes all of it.

Key chaos. Separate SSH keys per account. Signed-commit requirements per org. Pick the wrong one, and your ten-second commit turns into a debugging session or a rejected pipeline. You’re not writing code anymore — you’re playing key-ring roulette.

The cognitive tax. This is the one that hurts most. It’s not the time. It’s the interruption — that fraction of a second where your brain leaves the problem you were solving and asks: am I the right person right now? That fracture in flow state is more expensive than any of the others. Because you don’t just lose the seconds. You lose the immersion.


The DIY Rabbit Hole

I did the math one week. By Wednesday, I’d already lost count.

Not because I’m disorganised. Because every repo, every client, every org has its own rules — and Git, for all its brilliance, has no mechanism to say “you’re in the work directory, here’s your work hat.”

I tried to fix it the way any engineer would. Aliases. Shell scripts. A half-baked direnv setup that worked 80% of the time and failed catastrophically the other 20. Each time, I’d patch one hole, and a new context would open up — different SSH key, stricter GPG policy, a client who wanted commits signed with their specific subkey.

I even tried the obvious shortcut: gh auth switch. It’s a toggle. You flip it, it changes your GitHub context, but it doesn’t touch your global Git config. It doesn’t remember that this directory needs a specific SSH agent. It doesn’t manage GPG signatures. It’s a solution for bouncing between GitHub accounts — but it doesn’t solve the core cognitive problem: the decision-making. A manual light switch when I needed a motion sensor.

But the real WTF? It wasn’t any of that. It was realising I’d just accepted this as normal. Like pausing before every push to mentally run a checklist was just… part of the job.

That’s when I stopped blaming myself and started looking at the seam.


The Organisational Paper-Cut

And I’m not alone in this. What’s a paper-cut for me is a process cost at scale.

Senior engineers burn time on other people’s auth failures. New hires lose their first hour to Git setup instead of shipping code. In regulated environments, a misattributed commit isn’t just embarrassing — it’s an audit flag. The individual friction becomes organisational drag.

The code is almost never the problem. The identity attached to it is.


Enter Grit

So I built something that sits exactly at that seam.

Not another wrapper. Not a custom Git command you have to remember. A background daemon that watches where you’re working and applies the right identity before you commit. Automatically.

I called it Grit.

The design was simple: make the decision once, then forget it exists.

Instead of switching configs manually, Grit remembers which identity belongs to which context. You tell it once — “this directory is work, this remote is my open-source account, this repo needs a signed commit” — and it handles the rest.


How It Actually Works

Detection rules. Define patterns once — directory paths, remote URLs, even repo names. Grit matches where you are and applies the right profile. No commands, no toggles.

~/work/bank-client/*     → Work Profile (SSH: work-key, GPG: on)
~/oss/*                  → Personal Profile (SSH: personal-key, GPG: off)
github.com/my-company/*  → Corporate Profile (signed commits required)

Pre-commit protection. This is the part I’m most proud of. A Git hook that verifies your identity before the commit is created, not after you’ve already pushed and someone points out the mistake. It’s defense-in-depth — the daemon handles the happy path, the hook guards the edge cases.

Per-profile keys. Each identity carries its own SSH key and GPG signing config. No more debugging which agent loaded which key. No more rejected pipelines because you used the wrong signature.

Session memory. Grit restores the right identity when you return to a repo. Open a project you haven’t touched in months — it picks up where you left off.

And it runs quietly in the background. Windows, Linux, macOS. Offline-first. No cloud, no telemetry, no account required.


The Hard Part

The hardest part wasn’t the switching. That’s one shell command. The challenge was building a decision engine that handles ambiguity gracefully.

What happens when a path matches two rules? What if there’s no rule? What if the remote URL doesn’t match anything I’ve defined?

I built a fallback chain: explicit .grit file in the repo → directory rules → remote patterns → explicit session override → global config. There’s always a fallback, and you always know which one applied.

That’s the architectural muscle I’ve spent two decades building — pointed at a paper-cut I lived with every single day.


Try It Today

It’s on PyPI if you want to give it a shot:

pip install grit-cli

grit setup            # one-time init
grit profile add      # add your identities
grit session set work # set context for this repo

Once your detection rules are in place, you stop running these commands. Grit just… works.

The best developer tools are the ones you stop noticing. Software is complex enough; the right Git identity should just be applied, every time, without costing you a single thought.

Grit is MIT-licensed and open source. Try it on your messiest repo today. If it breaks, open an issue — I’m fixing things within 24 hours right now.

See the code on GitHub →

If you’ve ever force-pushed to fix a wrong-identity commit — what happened? I’d genuinely love to hear it.