Command reference for rgit. For the reasoning behind these choices see
specs/design.md; for anchor syntax see
ANCHORS.md.
$ rgit diff
auth.go ValidateToken +12/-3
oldHelper DELETED +0/-14
@imports +1/-0
(unanchorable) +2/-0 -> use --file auth.go
README.md (no symbols) +2/-0
newfile.go @header +2/-0
NewFunc +13/-0
config.ini (untracked) +4/-0 -> use --file config.ini
script.sh (mode 644->755) +0/-0 -> use rgit commit script.sh
logo.png (binary) -/-
$ rgit commit -m "auth: reject expired tokens" \
auth.go:ValidateToken auth.go:@importsnewfile.go is untracked (never git added) but attributes per symbol
exactly like a brand-new tracked file — there is no HEAD blob to diff
against, so every declared symbol is wholly new. config.ini stays a single
collapsed (untracked) row because it has no grammar to attribute by; a
binary untracked file collapses the same way.
Three, all given before the command: -C <path>, --version, and
-h/--help (the latter two under § Help).
-C <path> runs as if rgit had been started in <path>, exactly as
git -C <path> does — the repository is discovered from there, and a
relative pathspec or anchor resolves against it, so passing -C is
indistinguishable from having stood there:
rgit -C ~/src/api diff --porcelain
rgit -C ~/src/api commit -m "fix(auth): reject expired" auth.go:ValidateTokenIt must come before the command, because git commit -C <commit> already
means "reuse that commit's message" and the two spellings must not collide.
Repeats accumulate, each read relative to the last (-C a -C b is -C a/b,
an absolute path resetting), and -C "" is a no-op — git's own semantics in
each case.
The directory is checked before the command runs, so both refusals reach
even a command that never opens a repository: no directory argument at all
is a usage error (129), and a directory rgit cannot enter is fatal (128).
The glued -C<path> spelling is a usage error, as it is in git.
Positional arguments carry everything: pathspecs, revisions, and symbol anchors.
--file and --sym exist as explicit equivalents for scripting and
disambiguation, never as requirements.
All git pathspec magic is leading-colon (:(exclude), :(glob), :/). An
interior colon is therefore free for FILE:NAME and needs no flag.
For diff, a bare A..B or A...B positional is pulled out before the
precedence table below ever runs. git rev-parse --verify (rule 3) fails
outright on range syntax, so a range token would otherwise fall through
every rule to an unresolvable-argument error instead of selecting a scope.
Only a token with no existing worktree, index, or HEAD path of that exact name is
treated as a range — git forbids .. in ref names, but a legitimate
relative pathspec like ../shared/util.go also contains .., and path
existence wins over the heuristic. At most one such token is accepted per
invocation; a second is a usage error (exit 129). --range is the explicit
form of the same value and is mutually exclusive with the positional one.
Resolution precedence, first match wins:
| # | Test | Result |
|---|---|---|
| 1 | Appears after -- |
Pathspec, always |
| 2 | Starts with : |
Git pathspec magic, passed through verbatim |
| 3 | (diff only) resolves via git rev-parse --verify |
Revision, or a rev:path blob reference — see below |
| 4 | Names a path existing in the worktree, index, or HEAD | Pathspec |
| 5 | Splits at the last : into an existing path + a name |
Symbol anchor |
| 6 | None of the above | Error listing each interpretation tried |
No escaping is ever needed. src/notes:draft.md is a legal path, so rule 4
claims it; auth.go:ValidateToken names nothing, so rule 5 splits it. Use
--sym or --file to force the reading when a repo genuinely has both.
Rule 3 splits at the first colon (HEAD~1:f.go is revision HEAD~1,
path f.go), where rule 5 splits at the last — each rule uses the
split git's own syntax needs at that position, not a shared convention.
rev:path is real git diff syntax (git diff HEAD~1:f.go HEAD:f.go
compares two blobs directly), and rule 3 exists first so it classifies
correctly rather than being misread as a FILE:NAME anchor by rule 5.
Exactly two rev:path positionals naming the identical path compare
that one file across two revisions, attributed by symbol like any other
scope: rgit diff HEAD~1:auth.go HEAD:auth.go. --sym still narrows
rendering afterward, exactly as it does everywhere else. This is the one
scope with no trailing pathspec of its own — git diff <blob> <blob> takes
none, and the two blob refs already name the file completely — so
combining it with --file/a pathspec, --staged/--unstaged, a revision
range, or bare revision positionals is refused (exit 129). A single,
unpaired rev:path positional is refused the same way: comparing two
arbitrary blobs by revision names no single changed file to group rows
under, and there is no honest guess for what the missing partner would
have been. Name the file directly instead when you only meant a plain
revision-scoped diff.
Paths are relative to the directory you run in, not the repository root —
git's own rule. From a subdirectory, naming a.go stages that directory's
a.go under the repo root, and naming the root-relative path from there
doubles the subdirectory prefix and finds nothing — exactly as git add
behaves. Leading-colon magic is the exception git already defines: :/ and
:(top) are root-relative wherever you stand.
Output is always root-relative, matching git diff --numstat.
Files and symbols mix freely in one invocation:
rgit commit -m "chore: bump deps" package.json bun.lock
rgit commit -m "fix(auth): reject expired" auth.go:ValidateToken auth.go:@imports
rgit commit -m "docs: note expiry" README.md auth.go:ValidateToken
rgit diff main...HEAD -- src/Pathspecs are passed to git verbatim, so every pathspec form works:
rgit commit -m "chore: format" 'src/*.go'
rgit commit -m "chore: sweep" . ':(exclude)docs/*'
rgit diff ':/src'rgit diff with no arguments shows everything committable: staged +
unstaged versus HEAD, plus untracked files. That is deliberately
git diff HEAD ∪ untracked, not git diff — the default answers "what
would rgit commit pick up". Narrower scopes use git's own flag names:
| Scope | Flag | Git equivalent |
|---|---|---|
| Everything committable (default) | — | git diff HEAD + untracked |
| Unstaged only | --unstaged |
git diff |
| Staged only | --staged / --cached |
git diff --staged |
| Revision range | positional or --range |
git diff A..B / A...B |
--sym and --file filter output to specific targets; when filtered by
--sym, (unanchorable) hunks in that file are omitted. Filtering matches the
anchor's resolved canonical form, so a gopls-style (*A).Get or a heading's
raw text filters correctly even though rgit diff itself only ever emits the
canonical spelling.
On a repository with no commits yet there is no HEAD to compare against, and
git diff HEAD fails outright. The default scope falls back to the empty tree,
so everything staged or untracked lists as an addition — rgit diff answers
the same question in a fresh git init that it does anywhere else, and
rgit commit writes the root commit.
Plain text only. The default is the aligned layout shown above;
--porcelain replaces it with stable tab-separated records.
The record layouts, the STATUS tokens, and the ordering guarantee are
specified in CODES.md.
A chmod +x with no content edit produces no changed symbols, so rgit diff
lists it as a MODE entry — the file is never falsely reported clean. Stage it
with a pathspec (rgit commit script.sh); --sym cannot express a mode change.
--sym FILE:member on a member of a class/container new to HEAD prints a
[warning] on stderr: rgit commit would stage the whole container, not just
the named member, since there is no way to add a member to a container that
does not exist yet (see ANCHORS.md). The
unfiltered listing never warns — every sibling already has its own row there.
-p/--patch appends git's own real patch body after the aligned/porcelain
report, unmodified — not a second diff format rgit invents, the same
framing as log -p and blame --porcelain. It covers the identical scope
and pathspec filter as the report above it, since both are derived from the
same comparison. Mutually exclusive with --porcelain; the default output
with neither flag is unaffected by -p's existence.
$ rgit blame auth.go:ValidateToken
^1a2b3c4 (Alice Example 2024-01-15 10:00:00 -0800 9) func ValidateToken(tok string) error {
5d6e7f8 (Bob Example 2024-03-02 14:22:11 -0800 10) if tok == "" {
...rgit blame FILE:SYMBOL resolves the anchor exactly like commit and diff --sym do, then runs git blame -L start,end -- FILE bounded to just that
symbol's own extent in the current worktree file — never the whole file.
There is no revision argument. When the worktree copy exists, blame reads it,
the same file a bare git blame FILE would. When the file has been deleted
from the worktree, rgit resolves the extent from HEAD and runs git blame
against HEAD for that same blob and line range.
--follow-rename follows the symbol across rename boundaries using the same
rename-boundary re-resolution as log --follow-rename: when git identifies a
rename, rgit resolves the symbol once against the pre-rename blob and blames
that segment's line range. It does not re-parse once per commit. With this flag,
every resolution uses the HEAD blob, never the dirty worktree. Without this
flag, blame keeps the behavior above, including its HEAD fallback when the
worktree file is gone.
An anchor that does not resolve is never silently widened to a whole-file
blame — it is exit 3 (unresolvable), 4 (ambiguous), or 9 (unsupported
language), the same codes commit and diff --sym already give the
identical anchor. See CODES.md.
-p is accepted alongside --porcelain as its exact alias, matching git
blame's own flag: unlike git log -p or git diff -p, git blame's own -p
already means --porcelain, not "patch" — blame annotates lines, it does
not diff them, so there is no separate patch mode to opt into.
--porcelain passes straight through to git's own git blame --porcelain
output, unmodified — not a second record format rgit invents. The default is
likewise git's own human-readable blame output, unmodified. See
CODES.md.
$ rgit log auth.go:ValidateToken
a1b2c3d fix(auth): reject expired tokens
9e8f7d6 feat(auth): add ValidateTokenrgit log FILE:SYMBOL resolves the anchor exactly like commit, diff --sym, and blame do, then runs git log -L start,end:FILE bounded to that
symbol's own extent — one record per commit whose own diff touched it, newest
first. Patch-free by default: plain git log -L always prints the full
patch body for every touching commit, which is precisely the flood this
command exists to avoid. Pass -p/--patch to see it anyway — git's own
git log -L output, unmodified, not a second patch format rgit invents.
--since=DATE and --until=DATE may be added to this anchor form; the
FILE:SYMBOL positional keeps its symbol-scoped meaning, and the bounds are
forwarded to git's own git log -L. -n N/--max-count=N can be combined
with it as well. --follow-rename may be combined with either date bound;
each rename segment receives the same filters. Under --follow-rename,
-n/--max-count applies independently to each rename segment, so the total
can exceed N when history crosses multiple renames.
Unlike default blame (worktree first), the anchor is resolved against
HEAD, not the worktree: history is a question about what has already
been committed, and git log -L itself walks HEAD's own history with no
notion of the worktree at all. (blame --follow-rename uses the same
HEAD-blob rule.) This also means a symbol already deleted from the
worktree, but still present in HEAD, keeps its history reachable — there
is nothing to open on disk, so rgit log never needs to.
git log -L already follows a rename on its own whenever git's own content
similarity detects one, the same as git log --follow — but it tracks the
line range through the rename by diff, not by re-parsing the old file, so
a rename that also reshuffles the symbol's position (or otherwise breaks the
line-level correspondence) can silently stop short. --follow-rename
re-resolves the anchor with tree-sitter against the pre-rename blob at each
rename boundary instead of trusting that line-tracking, and continues under
the pre-rename path from there. Either way, the anchor must resolve at HEAD
under the file's current name — querying by a prior name directly fails
at argument classification. See
LIMITATIONS.md.
An anchor that does not resolve is exit 3 (unresolvable), 4 (ambiguous), or 9
(unsupported language) — the same codes blame, commit, and diff --sym
already give the identical anchor. See CODES.md.
--porcelain lists stable tab-separated HASH<TAB>SUBJECT records instead of
the aligned <abbrev-hash> <subject> default, no header. Mutually exclusive
with -p/--patch. See CODES.md.
$ rgit log new.go:Foo --follow-rename
b6f3975 edit
2793187 rename + reorder
c8fdd8a init--follow-rename continues a symbol's history past a rename that plain log FILE:SYMBOL stops at, one rename boundary at a time (not a per-commit
re-parse): at each commit git's own follow detects as a rename, the anchor
is re-resolved with tree-sitter against the pre-rename blob one commit
earlier, and history continues under that path. Without the flag, behaviour
is unchanged. See LIMITATIONS.md.
$ rgit log --since=2024-01-01 -n 5 -- src/auth
a1b2c3d fix(auth): reject expired tokens--since=DATE or --until=DATE (either alone, or together) selects ordinary
git history bounded by date only when no positional is a FILE:SYMBOL
anchor. With an anchor, the symbol-scoped form above remains selected.
Otherwise, one or more trailing positionals are pathspecs. Values are
forwarded to git's own --since/--until unparsed, so anything git accepts
there ("2024-01-01", "2 weeks ago") works here too. With no paths, the
unanchored form is the whole repository's history in that window, matching
plain git log --since=DATE.
-n N/--max-count=N limits either form to at most N commits, forwarding
git's own count limit. Without either spelling, the history remains unbounded.
This is the one git log carve-out rgit's own "the tree is only ever
inspected through rgit" convention otherwise has to make for a plain
git log --since=... -- <paths> — closed by giving rgit log a second
invocation shape rather than a second command. --porcelain and -p/
--patch behave identically to the FILE:SYMBOL form above: patch-free
aligned records by default, --porcelain's tab-separated form on request,
and the real patch body only when -p/--patch is given, mutually
exclusive with --porcelain.
B<TAB>main<TAB>origin/main<TAB>0<TAB>2
S<TAB>merge
W<TAB>ts-only
W<TAB>warning<TAB>extent disagreement reported on stderr
F<TAB>auth.go<TAB>ValidateToken<TAB>MOD<TAB>12<TAB>3
F<TAB>config.ini<TAB><TAB>UNTRACKED<TAB>4<TAB>0
C<TAB>a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2<TAB>fix(auth): reject expired tokens
C<TAB>9e8f7d6c5b4a9e8f7d6c5b4a9e8f7d6c5b4a9e8f<TAB>feat(auth): add ValidateToken
rgit context is one-call repository orientation for an agent's first turn:
the current branch and its upstream tracking status, then the same per-file,
per-symbol diffstat rgit diff itself reports for everything committable,
then recent commit subjects — as a single, fixed-shape record stream. It
replaces the separate status, diff --stat, diff, and log calls an
agent would otherwise make before editing, each billed as its own subprocess
call.
The output shape is fixed and takes no flags beyond --help. A command
with options becomes git status with extra steps — see
specs/design.md for why the shape stays
fixed rather than growing one. Seven record types, tab-separated, no header:
| Record | Fields | Meaning |
|---|---|---|
B |
BRANCH, UPSTREAM, AHEAD, BEHIND |
At most one, first when present: the current branch. UPSTREAM is empty and AHEAD/BEHIND are both 0 with no upstream configured. Absent on an unborn branch and replaced by H on detached HEAD |
H |
SHA |
One detached-HEAD record with the full commit object id; absent on an unborn branch |
S |
OP |
One active sequencer operation: merge, cherry-pick, revert, rebase, or bisect |
W |
ts-only |
One when at least one file had symbols to cross-check but no live language server was reached. The identical [ts-only] notice remains on stderr |
W |
stash |
One when refs/stash exists. Absent when the stash is empty |
W |
sparse |
One when core.sparseCheckout is true. Absent on a full checkout |
W |
warning, TEXT |
One per non-fatal diff warning. TEXT is the warning body without the human [warning] prefix; the identical [warning] TEXT line remains on stderr |
F |
FILE, SYMBOL, STATUS, ADDED, DELETED |
One per rgit diff --porcelain row — identical fields, plus this stream's own leading type tag |
C |
HASH, SUBJECT |
One per recent commit, newest first, bounded to the last 20 |
X |
TRUNCATED, COUNT |
At most one, always last: this many records were withheld to hold the byte budget |
The diff half is pure composition, not a second attribution path: it is
literally rgit diff's own default scope (everything committable), rendered
through the same --porcelain records and re-tagged per line.
The whole stream is capped at 16 KiB. B or H, when present, sorts first
— a single record that costs the budget almost nothing — then S, W
diagnostics and F rows. F rows survive truncation before C rows do. The diff section is
the unbounded, actionable half and has no natural limit of its own; commits
are already bounded up front (the most recent 20, via git's own history limit)
and cost little to drop, so a busy branch sheds commit history before it ever
shortens the diff. Truncation happens at the byte boundary, with a trailing
X record naming how many rows were withheld. See
../specs/design.md for the reasoning. See
CODES.md for the exact record grammar.
rgit --help, rgit -h, and rgit help print the top-level command list on
stdout and exit 0. rgit diff --help / -h and rgit commit --help / -h
print that command's own flags the same way, generated from the flag set itself
so the two cannot drift. rgit blame --help, rgit log --help, rgit context --help, rgit languages --help, rgit doctor --help, rgit symbols --help, and rgit completion --help (each also accepting -h)
print their own hand-written usage text instead — surfaces small enough that a
generated rendering was not worth building. A bare rgit (no command at all)
is a usage error, not a help request — see § Exit codes.
rgit --version prints rgit <version> on its first line and exits 0:
$ rgit --version
rgit v1.3.0
optional grammars: sql
built with go1.26.6, linux/amd64The version is stamped at build time (-ldflags "-X main.version=vX.Y.Z"),
which make install and cmd/rgit-install both do. Without it, the version
is recovered from what the toolchain embeds: a go install …@vX.Y.Z from the
module proxy reports that tag, and a plain go build inside a checkout
reports the abbreviated revision with -dirty where it applies — the same
shape git describe --tags --always --dirty produces. Only a build with
neither, such as one made outside a checkout or with -buildvcs=false, reads
dev.
That first line is the only one scripts should parse. The lines after it are free to grow: a second reports which optional/gated grammars this exact binary was compiled with (see § Languages below), so it can change independently of the version, and a third names the Go toolchain and platform it was built for — two binaries can report the same version and still differ there, which is what a bug report needs and what the reporter rarely thinks to include.
rgit languages lists every grammar compiled into the running binary: name,
file extensions, and whether it is present only because a build tag selected
it.
SQL is the first grammar gated this way — -tags rgit_sql, generated by
cmd/rgit-install when the tree-sitter CLI is on PATH, see
INSTALL.md — so the identical binary can answer
"what do you support" two different ways depending on how it was built.
rgit --version's second line names the same gated grammars, so telling a
SQL-enabled binary from a plain one never needs a separate command.
$ rgit languages
css .css
go .go
html .html .htm
json .json
markdown .md .markdown
python .py .pyi
shell .sh .bash
sql .sql (build-tag gated)
toml .toml
tsx .tsx .jsx .js .mjs .cjs
typescript .ts .mts .cts
yaml .yaml .ymlThis sample is from a -tags rgit_sql build; a plain go build/go install
omits the sql row entirely (see INSTALL.md).
--porcelain replaces the aligned listing with stable
NAME<TAB>EXTENSIONS<TAB>GATED<TAB>CROSS-CHECK records; the first three
columns retain the meanings above.
CROSS-CHECK is wired for grammars with
a language-server catalog entry and ts-only for TOML and SQL.
It reports
compile-time design wiring, not whether a server is reachable in this
invocation; rgit doctor reports that environment status.
A .sql anchor on a binary built without rgit_sql still fails with exit 9
("no grammar registered"), the same as any genuinely unsupported language —
but unlike one this resolver has never supported, the message also names the
build tag and points at rebuilding.
--in-repo narrows the listing to grammars with at least one matching
file in the current repository — advisory only, since the binary
still contains every compiled-in grammar regardless of what a given repo
happens to use.
A monorepo with only .go files omits python, css, and
the rest even though a Python or CSS anchor would resolve fine elsewhere.
Detection reuses the same extension-then-shebang sequence every worktree file
gets; tracked files fall back to a bounded HEAD sample when their worktree
copy is absent, and untracked files (excluding ignored ones) count too.
Requires a git repo, unlike the plain form above.
rgit doctor reports environment health: git on PATH (the one thing rgit
cannot run without) and its resolved version against the floor
INSTALL.md documents, the optional tree-sitter
CLI, which language servers from
INSTALL.md answer on PATH for the extent
cross-check, and the same grammar listing rgit languages prints.
It exits
0 unless rgit genuinely cannot function — a missing language server, the
tree-sitter CLI, or a below-floor git version is informational, since
degraded [ts-only] resolution is normal and documented, not an error (see
CODES.md).
--porcelain lists the environment and language-server checks as stable
tab-separated records instead — see
CODES.md — for agents and CI that want
a parseable stream rather than the aligned human report.
It does not repeat
the grammar listing; rgit languages --porcelain already owns that.
--deep dials each on-PATH server for real — the identical
initialize/initialized handshake rgit diff/rgit commit already perform
for the cross-check — and appends (reachable) or (degraded — handshake timed out or unanswered) to its detail column.
A binary being on PATH is
not proof it actually answers; a stale daemon or a cold index both look
identical to a plain LookPath check but differ under --deep.
Slower than the default for exactly that reason, and not the default: a cold CI host with nothing installed should stay instant.
A server not on PATH at all is
never dialed — there is nothing to dial, and MISSING already says
everything --deep could add.
$ rgit symbols auth.go
@imports
ValidateTokenrgit symbols [--for-commit] [--with-lines] <file> lists every declared symbol
that can be resolved from the worktree file, or from the file's HEAD blob when
the worktree copy has been deleted, one symbol per line. A path present in
neither the worktree nor HEAD still errors. --for-commit omits
structured-data symbols that rgit commit refuses; it still exits successfully
without output when the file is a supported structured-data file.
--with-lines emits each symbol's line range ahead of its anchor instead of the
bare name, and composes with --for-commit:
$ rgit symbols --with-lines auth.go
1,3 @imports
12,27 ValidateTokenThe range is git's own -L start,end range for that symbol — the same range
rgit blame FILE:SYMBOL and rgit log FILE:SYMBOL bound themselves to — so it
can be handed straight to a reader that takes a line range. The record format is
in CODES.md.
--help/-h prints the command's usage text and exits 0. Exactly one file
argument is required; a missing or extra argument prints the usage text to
stderr and exits with the invalid-usage code. A file that cannot be read from
either source or whose symbols cannot be resolved exits with the git-failure
code, while an unsupported language exits with the unsupported-language code.
See
CODES.md.
When core.ignorecase is true, extension lookup is case-insensitive for
symbols, commit, diff, blame, log, and languages; the path itself
remains unchanged.
rgit completion bash, rgit completion zsh, rgit completion fish, and
rgit completion pwsh print a completion script for that shell to stdout;
nothing else is written.
PowerShell registration instructions are in
INSTALL.md.
It completes subcommands, each subcommand's own flags, plain file paths, and
— the useful part — symbol names after FILE:, by shelling back out to
rgit symbols FILE.
That read-only command lists every declared symbol in
the worktree file, or the HEAD blob when that copy is gone, so completion
works for clean, dirty, and deleted-but-tracked files.
If
that call fails for any reason — the working directory is not a repository,
rgit is not on PATH, anything — completion offers nothing rather than
printing to the prompt.
rgit symbols FILE itself prints one anchor per
line and is useful for scripts that need the same list.
Completion for
commit uses rgit symbols --for-commit FILE, which omits structured-data
symbols that commit refuses; other commands use the complete list.
The fish and pwsh scripts drive the identical logic through their shells' own
completion models — fish's dynamic candidate function registered with
complete and PowerShell's native completer, rather than bash's
COMPREPLY/compgen or zsh's compadd — but complete the same things the
same way, including the -C <path> walk and the FILE:SYMBOL lookup.
An unrecognized or missing shell argument is a usage error, same table as
everywhere else. Install instructions: INSTALL.md.
commit and diff document their flags in the table below; hand-parsed meta
commands carry smaller surfaces of their own: blame takes
-p/--porcelain, --follow-rename, and
--help; languages takes --porcelain, --in-repo, and --help (§
Blame and § Languages above, CODES.md); log
additionally takes -p/--patch, mutually exclusive with --porcelain,
--follow-rename, -n/--max-count, and — only in its
--since/--until shape — --since/--until themselves (§ Log and § Log
by date and path above); symbols takes --for-commit, --with-lines, and
--help (§ Symbols above); doctor takes --porcelain, --deep, and --help;
completion and context take no flags beyond --help/-h
(completion also takes its shell argument; context's fixed output shape
is the point — § Context above).
| Flag | Behavior |
|---|---|
--sym FILE:NAME |
Explicit anchor form; equivalent to a bare FILE:NAME positional. Repeatable. |
--file PATH |
Explicit pathspec form; equivalent to a bare positional. Repeatable. |
--pathspec-from-file FILE |
(commit, diff) Read one target per line from FILE, or from stdin when FILE is -. Empty lines are skipped; targets use the same precedence rules as positionals. Mutually exclusive with -F - when both would consume stdin (exit 129). |
--pathspec-file-nul |
(commit, diff) Read NUL-delimited targets from --pathspec-from-file instead of newline-delimited lines. Empty records are skipped. |
-m MSG, --message MSG |
Commit message. Repeatable — values join as blank-line-separated paragraphs, as git does. |
-F FILE, --message-file FILE |
Read the message from a file, or - for stdin. Mutually exclusive with -m. |
-s, --signoff |
Append Signed-off-by:. Forwarded to git commit. |
--trailer TOKEN:VALUE |
Append a trailer (Refs:, Co-authored-by:). Repeatable, forwarded. |
--amend |
Amend the previous commit. Anchors stage into it as they would a new commit. With neither -m nor -F, reuses HEAD's message unchanged (--no-edit) — rgit never opens an editor, so that is the only message an unattended --amend can have. Give -m/-F to replace it as usual. With no targets, skips staging and amends the index as it stands. |
--allow-empty |
Permit a commit with no changes. Suppresses exit 11. With no targets, skips staging and commits the index as it stands; still requires -m/-F unless another auto-message flag is set. |
-o, --only |
Commit only the named targets, leaving other staged paths in the index. Requires at least one target unless combined with --amend; anchors still synthesize their named extents before the commit. |
--reuse-message=<commit> |
Reuse that commit's log message and authorship (git commit --reuse-message). Long form only — global -C is directory chdir and stays before the command. Mutually exclusive with -m the way git is (-m and -C cannot be used together). Does not require a separate -m. |
--reedit-message |
Refused (exit 129). rgit never opens an editor; use --reuse-message. |
--push |
Push upstream after a successful commit. No rollback on push failure. If the branch has no upstream configured, the exit-8 message names it and the fix (git push -u origin <branch>, or push.autoSetupRemote) — rgit never adds -u itself. |
--dry-run |
Preview only. Writes no objects, stages nothing, runs no hooks. Lists each target it resolved with that symbol's +N/-M, using the same counts as rgit diff. |
--no-verify |
Skip git hooks (standard git meaning). Hooks run by default. |
--fixup <commit> |
Autosquash fixup for <commit> (also accepts amend:<commit>/reword:<commit>, forwarded verbatim). Generates its own subject, so -m/-F are not required; either still appends as an extra body paragraph rather than conflicting. |
--squash <commit> |
Autosquash squash for <commit>. Same message rule as --fixup. |
--author <author> |
Override the commit author. Plain forwarding. |
--date <date> |
Override the commit date. Plain forwarding. |
--reset-author |
Take the author identity from the committer instead of carrying the original forward. Plain forwarding; git accepts it only with --amend or --fixup=amend:, and rgit does not police the combination. |
--porcelain |
(commit) After a successful real commit, emit a leading H<TAB>SHA record with the full commit object id, followed by stable tab-separated target records instead of the aligned listing. Replaces git commit's own summary rather than adding to it, exactly as git commit --porcelain does. Works with --dry-run, which emits target records alone with no H record or preamble. |
-q, --quiet |
(commit) Suppress the summary and the target listing. stdout is empty; warnings, notices and hook output still go to stderr, as under git's own -q. |
-S, -S<key-id>, --gpg-sign, --gpg-sign=<key-id> |
GPG-sign the commit, with the configured default key or an explicit one. See the note below on how -S is parsed. |
--no-gpg-sign |
Do not GPG-sign, overriding commit.gpgsign=true. |
--unstaged |
(diff) Worktree vs index — git's bare diff. |
--staged, --cached |
(diff) Index vs HEAD. Both spellings. |
--range REVS |
(diff) Explicit form of a positional revision range. |
--porcelain |
(diff) Stable tab-separated records. |
--exit-code |
(diff) Exit 1 when anything is committable, 0 when clean. |
--quiet |
(diff) Implies --exit-code and suppresses output. |
-p, --patch |
(diff) Append git's own real patch body after the report. Suppressed by --quiet, mutually exclusive with --porcelain. |
--since DATE, --until DATE |
(log) Bound history by date. A FILE:SYMBOL positional keeps the anchor form; otherwise these select unanchored path-scoped history. Forwarded to git's own --since/--until unparsed. |
-n N, --max-count=N |
(log) Limit either history form to at most N commits; under --follow-rename, applies independently per rename segment, so the total may exceed N. Forwarded to git's own count limit; omitted by default, so history is unbounded. |
commit requires a message (-m or -F) unless --amend, --fixup,
--squash, or --reuse-message is given — each supplies its own message
(--amend reuses HEAD's via --no-edit; --fixup/--squash generate
fixup!/squash! <subject>; --reuse-message takes the named commit's,
exactly as plain git commit does). It also requires at least one target,
unless --amend, --allow-empty, --fixup, --squash, or
--reuse-message is set: zero
targets means skip staging and operate on the index as it stands, not
git add -A.
During an in-progress merge, cherry-pick, or revert, omitting -m and -F
also reuses Git's generated message via --no-edit; -m or -F overrides
that behavior. An in-progress rebase remains a git rebase --continue
operation and still requires a message here.
-S is accepted in git's own spellings: bare -S, or -S<key-id> with the
key attached. It is rewritten to the long form before the flag parser runs,
because pflag resolves an optional-value shorthand's default before checking
for an attached value, so a registered -S would read -SDEADBEEF as a chain
of nonexistent single-letter flags. Following getopt (and git), everything
after -S in the same token is the key id — -Ss means the key s. Packing
S into a chain behind other shorthands (-sS) is not supported and is
refused by name rather than misread.
On success it relays git commit's own summary — branch, new SHA, and the
changed/insertion/deletion counts — then lists each staged target with its
+N/-M, which git cannot report because git does not know about symbols. Hook
output is passed through too. --dry-run prints the same listing, so a preview
and the commit it previews are comparable line for line, and neither needs a
follow-up git show or rgit diff to interpret.
--porcelain replaces both with stable tab-separated records — a successful
real commit starts with its full commit object id, then the target rows. The
schema and rationale are in CODES.md:
H<TAB>SHA
H<TAB>a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
auth.go<TAB>ValidateToken<TAB>12<TAB>3
The target records are identical for --dry-run and for the commit it
previews. Dry-run output has no H record; an --allow-empty commit emits
H even when it has no target rows. --quiet continues to leave stdout empty.
Repeatable -m gives subject and body without embedding newlines in one shell
argument:
$ rgit commit -m "fix(auth): reject expired tokens" \
-m "Tokens past exp were accepted because the clock check ran
before decode. Closes #42." \
auth.go:ValidateTokenInvalid combinations: --dry-run + --push, --staged/--unstaged +
a revision argument (a range, or one or two bare revisions), --staged +
--unstaged, --range + a positional A..B/A...B range, -m + -F,
--porcelain + --quiet (diff), --porcelain + -p/--patch (diff,
log) → exit 129.
Naming one path both as a path and as a symbol anchor → exit 5, in
whichever spelling: --file with
--sym, or the positional forms greet.go greet.go:A.
A FILE:SYMBOL anchor into a structured-data file (JSON, YAML, TOML) → exit
12: a spliced extent is not guaranteed to agree with the file's own grammar,
and nothing would fail at commit time to say so. Name the path instead —
rgit commit package.json stages the whole file, unaffected; rgit diff,
rgit blame, and rgit log still resolve the identical anchor, since none
of them writes a blob (see CODES.md).
A missing conventional-commit shape (type(scope): subject) warns on stderr;
the commit proceeds.
rgit is git add <pathspec> && git commit at symbol granularity, so:
- Work you staged before invoking
rgitcomes along with the commit, unless--onlyis given. - A hook rejecting the commit leaves staging in place; nothing is rolled back.
- Hooks are not policed — a hook may stage paths you did not name, exactly as
under plain
git commit. Use--no-verifyto disable them. - During an in-progress merge, cherry-pick, or revert, omitting
-mand-Fuses Git's--no-editmessage reuse; rebase remainsgit rebase --continue. commit.cleanupandcommit.gpgsignare honoured as configuration, and--gpg-sign/--no-gpg-signoverride either.commit.templateis not honoured — templates prefill an editor andrgitnever opens one.rgitnever adds--set-upstreamto a push on its own initiative, even for a branch with none configured — see--pushabove.
When stdin is not a terminal, rgit sets GIT_TERMINAL_PROMPT=0 so a
credential or GPG prompt fails fast instead of hanging.
An ordinal anchor (auth.go:init#2, ANCHORS.md)
is positional — inserting a symbol above it repoints which one it names.
Resolving one prints an advisory on stderr, never fails the command:
[warning] anchor 'dup.go:init#2' is positional; inserting a symbol above it repoints it -- qualify it where the language allows
rgit commit, rgit diff --sym, rgit blame, and rgit log all print it
for the identical anchor — the same advisory everywhere an ordinal
resolves, not only at commit time. A bare or container-qualified anchor
that merely happens to match the same symbol never warns.
Naming a target that has no uncommitted changes is a warning, not a failure.
rgit prints one line per such target on stderr and commits the rest:
[warning] target 'auth.go:oldHelper' has no uncommitted changes; skipping
Exit is 11 only when every named target turned out unchanged — that is,
when there is genuinely nothing to commit. --allow-empty suppresses it.
Specified in CODES.md, along with which of them
each command can produce.