Files
fuckgit/CHANGELOG.md
T
swaits a059ee55a2 feat: redirect git invocations to jj inside jj repos
fuckgit installs as a Cargo bin literally named `git` (via
`[[bin]] name = "git"`). When invoked inside a jj worktree by an
AI agent, it prints the equivalent `jj` subcommand plus the live
`jj help <sub>` output to stderr and exits 2 — the AI sees a clear
failure and the right correction. Outside a jj repo, or with no
intercept marker, it is a transparent passthrough.

The intercept gate fires only when:
- effective cwd (after honoring `git -C`) is inside a `.jj` worktree
- FUCKGIT_INTERCEPT=1 or an AI marker (CLAUDECODE) is set
- subcommand is not on the plumbing allowlist
  (rev-parse, cat-file, for-each-ref, ...)
- GIT_DIR / GIT_EXEC_PATH / CARGO are not set
- no top-level --git-dir= / --work-tree= flag is present

Otherwise we walk PATH, skip self by canonicalized current_exe(),
and exec() the first other `git` we find — preserving signals,
exit code, and TTY ownership.

Escape hatches: FUCKGIT_PASSTHROUGH=1 env var, --fucking-git flag
(stripped before exec). FUCKGIT_DEPTH guard aborts at depth >= 2
to prevent self-recursion.

Linux and macOS, zero runtime dependencies.
2026-04-30 01:04:50 -06:00

2.1 KiB

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

0.1.0 - 2026-04-30

Added

  • Initial release.
  • Cargo binary literally named git (via [[bin]] name = "git") that shadows the real git on PATH.
  • Default-safe passthrough: outside a jj worktree, or with no intercept marker, every invocation is forwarded to the real git via exec() — preserving signals, exit code, and TTY ownership.
  • Intercept gate fires only when inside a .jj worktree (honoring git -C <path>) and either FUCKGIT_INTERCEPT=1 or an AI-agent marker env (currently CLAUDECODE) is set.
  • Redirect output: prints the matching jj subcommand plus live jj help <sub> output to stderr; exits with status 2.
  • Mapping table for 27 common 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).
  • Plumbing allowlist (rev-parse, symbolic-ref, for-each-ref, cat-file, update-ref, hash-object, ls-files, ls-tree, merge-base, show-ref, name-rev, var, credential, check-ref-format, version) for transparent passthrough so tooling keeps working.
  • Safety env passthroughs: GIT_DIR, GIT_EXEC_PATH (hook context); CARGO (cargo subprocess).
  • Top-level argv pre-pass handles -C <path>, -c <kv>, --git-dir[=<path>], --work-tree[=<path>], --namespace, --config-env, --exec-path, --paginate/--no-pager, --bare, --version/-v, --help/-h.
  • Escape hatches: FUCKGIT_PASSTHROUGH=1 env var, --fucking-git flag (stripped before exec).
  • Self-recursion guard via FUCKGIT_DEPTH env counter (aborts at depth ≥ 2).
  • Linux and macOS support. Zero runtime dependencies.