Skip to content

swaits/fuckgit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

fuckgit

A binary literally named git that, when run inside a jj (Jujutsu) repo, refuses to actually run git and instead tells you to use jj.

Why

AI coding agents (Claude Code, Cursor, et al.) keep running git inside jj-managed repos despite being told to use jj. In a colocated jj+git layout, that corrupts state. fuckgit shadows the real git on PATH and traps these invocations, redirecting them with the equivalent jj subcommand and inline jj help <subcmd> output.

It works on humans too, when they ask for it.

Install

cargo install fuckgit

This installs a binary named git (yes, really) to ~/.cargo/bin/git. Make sure ~/.cargo/bin is ahead of /usr/bin on PATH.

Linux and macOS only.

Behavior

By default, fuckgit is a silent passthrough — every git invocation is forwarded to the real git on PATH. The redirect only fires when all of these are true:

  1. You're inside a jj worktree (a .jj directory exists in the cwd or an ancestor — honoring git -C <path>).
  2. The intercept gate is open — at least one of:
    • FUCKGIT_INTERCEPT=1 is set, OR
    • an AI-agent marker env var is set (currently just CLAUDECODE).
  3. The subcommand isn't on the plumbing allowlist (rev-parse, cat-file, for-each-ref, …).
  4. None of the safety env vars are set: GIT_DIR, GIT_EXEC_PATH, CARGO.
  5. No top-level --git-dir= or --work-tree= flag is present.

If any check fails, git behaves exactly as if fuckgit weren't installed.

When the redirect does fire, you'll see something like:

Don't use git. Use jj.

  git status  →  jj st
  jj has no staging area; `jj st` shows the working-copy commit's diff.

--- jj help status ---
Show high-level repo status [default alias: st]
…

Override with FUCKGIT_PASSTHROUGH=1  or  git --fucking-git <args...>

…and exit 2.

Escape hatches

When you need real git and the intercept is firing:

  • FUCKGIT_PASSTHROUGH=1 git <args> — env var override
  • git --fucking-git <args> — flag override (the flag is stripped before exec'ing real git)

Configuration

Variable Effect
FUCKGIT_INTERCEPT=1 Open the intercept gate (opt in for your own jj repos).
FUCKGIT_PASSTHROUGH=1 Force passthrough even with the gate open.
CLAUDECODE Set by Claude Code; opens the gate automatically.

To extend the AI-marker list, edit AI_MARKERS in src/main.rs and rebuild.

Supported subcommands

fuckgit knows the jj equivalent for these git subcommands:

status, log, commit, add, checkout, switch, restore, branch, merge, rebase, pull, push, fetch, clone, init, diff, show, reset, revert, cherry-pick, stash, tag, blame, remote, bisect, config, reflog.

Unknown subcommands fall through to a generic "use jj instead" + jj help output.

License

MIT — see LICENSE.

About

A binary named `git` that redirects you to `jj` (Jujutsu) when invoked inside a jj repo.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages