Git diffs and logs

gnaw can fold live git context into the output so a model sees what you're working on now and how the code has moved, not just a static snapshot. There are several independent sources, each surfaced as its own section in the rendered prompt.

Working-tree diff

-d / --diff injects the current diff. --diff-mode chooses which changes, and requires --diff to be set.

--diff-modeDiff shown
staged (default)Staged changes only
unstagedUnstaged working-tree changes
allAll uncommitted changes
gnaw . --diff                      # staged (default)
gnaw . --diff --diff-mode unstaged
gnaw . --diff --diff-mode all

This populates the git_diff template variable, rendered under a <git-diff> tag (XML) or a Git Diff: heading (Markdown).

Diff between two branches

--git-diff-branch takes two refs (comma- or space-separated) and renders the diff between them:

gnaw . --git-diff-branch main,feature/login
gnaw . --git-diff-branch v1.0.0 HEAD

This populates git_diff_branch.

Log between two branches

--git-log-branch likewise takes two refs and injects the commit log across that range:

gnaw . --git-log-branch main,feature/login

This populates git_log_branch.

Per-file changed content between two refs

The diff sources above hand the model one unified patch. --git-diff-shas instead emits a per-file view of everything that changed between two refs: each changed file gets its own section with the chosen content, and the source tree is scoped to just those files rather than the whole repo. It's the right shape when you want the model to reason file-by-file about a range of commits.

--git-diff-shas accepts the two refs as ref1..ref2, ref1,ref2, or two space-separated tokens:

gnaw . --git-diff-shas main..feature/login
gnaw . --git-diff-shas v1.0.0,HEAD
gnaw . --git-diff-shas HEAD~3 HEAD

Renamed files are detected and labelled; binary files are reported as changed rather than silently dropped.

Choosing what each file shows

--git-diff-shas-content picks how much per-file content to emit. It requires --git-diff-shas.

ValuePer file
patchThe unified patch only (plus the full body for added files). Leanest, ~1ร— the changed content.
after-patch (default)The full after body of every changed file, plus the patch. No before.
fullFull before and after bodies, no patch. ~2ร—.
full-patchFull before and after plus the patch. Heaviest.
gnaw . --git-diff-shas main..HEAD --git-diff-shas-content patch
gnaw . --git-diff-shas main..HEAD --git-diff-shas-content full-patch

Capping large files

--git-diff-shas-max-bytes skips per-file content above the given byte size (0, the default, means no limit). Oversized files are reported as changed with their content left out. It also requires --git-diff-shas.

gnaw . --git-diff-shas main..HEAD --git-diff-shas-max-bytes 200000

Changed-files tree for git-narrative templates

The git-narrative built-in templates โ€” write-git-commit, write-git-changeset-commits, and write-github-pull-request โ€” only need to see which files the change touches, not the whole repository. When one of these is in effect (selected automatically by the git flags, or chosen explicitly with --template), gnaw scopes the rendered source tree to the changed files. The diff and log still render as their own sections; the tree just stops listing files that weren't part of the change.

  • A commit / changeset run (with --diff) scopes the tree to the working-tree changes for the active --diff-mode.
  • A pull-request run (with --git-diff-branch or --git-log-branch) scopes the tree to the files changed between the two refs.

A git-narrative template invoked without any git context (for example a bare --template write-git-commit) has nothing to scope to, so it falls back to the whole-repository tree.