Skip to content

Fix #19: support --summary in show, log and diff - #21

Merged
blindmansion merged 3 commits into
blindmansion:mainfrom
Hazzng:feat/summary-19
Oct 14, 2026
Merged

blindmansion merged 3 commits into
blindmansion:mainfrom
Hazzng:feat/summary-19

Conversation

@Hazzng

@Hazzng Hazzng commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Fixes #19

Summary

git show, git log and git diff now accept --summary. Before this change all three rejected it with Unknown option "--summary". The summary lists the files a change created, deleted, renamed or changed mode on, which is often all an agent needs from a commit.

Supported surface:

git show --summary [--stat | --shortstat | --numstat | -p] [<object>]
git log  --summary [--stat | --shortstat | --numstat | -p] [--oneline | --format=<fmt>] [--graph] ...
git diff --summary [--stat | --shortstat | --numstat] [--cached] [<commit> [<commit>]]

The lines match git 2.34.1 byte for byte:

 create mode 100644 n
 delete mode 100755 m
 mode change 100644 => 100755 n
 mode change 100755 => 120000 n          (type change)
 create mode 120000 link
 rename z => z2 (100%)
 rename dir/sub/{a => b} (100%)
 rename big => big2 (70%)
 mode change 100644 => 100755            (rename that also changed the mode)
 create mode 100644 "q\"uote"
 create mode 100644 "\303\251.txt"

Ordering follows git:

  • --summary on its own replaces the patch.
  • After --stat, --shortstat or --numstat it prints right after their output.
  • With -p it prints before the patch, with a blank line between them.
  • --name-only and --name-status drop it, and so does show --no-patch.
  • log prints nothing for merges, since it doesn't diff them by default.
  • A commit with changes but no summary lines, such as a content-only edit, still gets the blank line after its message. That is why git log --summary shows two blank lines after such a commit in medium format.

Before and after

$ git show --summary HEAD
# before (1.9.1): Unknown option "--summary".   rc=1
# after:
commit e91cbdcf157f110f5a97fdc92e2c9b0a1c21fab9
Author: a <a@b>
Date:   ...

    sum

 delete mode 100755 m
 create mode 100644 n
 rename z => z2 (100%)

How it works

formatSummaryLines in src/lib/commit-summary.ts is the only formatter for these lines. commit, merge, show, log and diff all call it. computeDiffStats used to build the create/delete lines for commit and merge as a side output. It now returns only the file stats, and the summary lines come from the new function.

Sharing the formatter changes the output of commit and merge in three cases, and in each case the new output is what git prints:

  • A mode change used to print as create mode 100755 n plus delete mode 100644 n. It now prints mode change 100644 => 100755 n.
  • A rename that also changed the mode now prints the pathless mode change line under the rename.
  • Paths that need it are C-quoted the way git's quote_c_style quotes them. If either side of a rename needs quoting, both sides print in full ("a" => "b") without the {a => b} form, as git's pprint_rename does.

In show and log the diff options now resolve to a main format plus a summary flag, and withSummary puts the two in git's order. log's formatCommitDiff returns null when it shows nothing at all (no diff option, a merge, an empty diff) and "" when the commit has changes but the output is empty. The difference is the blank line described above. diff maps its items to the same inputs and appends the summary.

The PR has two more commits, split out so they are easy to review or drop:

  • log --graph --format=<fmt> blank line. With --graph and a custom format, the diff output came right under the formatted line. Git puts a padded blank line there, the same as without --graph. Only --oneline skips it. This showed up as soon as I compared log --graph --format=%s --summary with git, and --stat had the same bug.
  • show on a merge. Git shows a merge's patch as a combined diff, but --stat, --shortstat, --numstat and --summary compare the merge with its first parent. just-git printed nothing for those formats on a merge, with a comment saying that matched git. It doesn't in 2.34.1, so show --summary <merge> would have printed nothing where git lists the merged-in files. Both now use the first parent. The name formats still print nothing on a merge.

Tests

  • In-memory tests with exact stdout, stderr and exit code. test/commands/show.test.ts has 11 new tests: summary alone, after --stat/--shortstat/--numstat, before -p, symlinks and quoted names, dir/sub/{a => b}, a type change, the blank line on a content-only commit, dropped by the name formats and --no-patch, through an annotated tag, and merges against the first parent. log.test.ts has 6, diff.test.ts has 6 (two commits, --cached, unstaged deletions, stat formats) and commit.test.ts has 1 for the mode-change lines. They share a history builder, setupSummaryHistory in test/util.ts.
  • test/interop/summary.test.ts builds a repo with real git, including an executable delete, a 70% rename that also gets +x, a symlink, a gitlink, a type change, names with a space, a quote, a tab and é, and a merge on its own branch. It runs 39 invocations of show, log and diff through both and asserts identical stdout, stderr and exit code. I checked that it catches defects. Turning off path quoting failed 9 cases, and dropping the pathless mode line under renames failed 14.
  • test/graph/scenarios/16-graph-with-summary.ts compares log --graph --summary with real git in medium, --oneline, --format and --stat forms. Scenario 09 gets two --graph --format cases for the blank-line fix.
  • Every new test failed before its change.
  • bun test: 3576 pass, 29 skip, 0 fail. On origin/main (b509001) it was 3512 pass, 29 skip, 0 fail, with local git 2.34.1. bun check is clean, and bun gen-docs updated docs/CLI.md and docs/FILE_REFERENCE.md.

Not included

These are gaps I hit while comparing with git. None of them come from --summary, and --stat or --name-status already show them on main:

  • git diff <commit> (commit against worktree) and git diff HEAD don't run rename detection, so a staged rename shows as a delete plus a create. --name-status does the same today.
  • git diff and git diff --cached don't see mode-only changes in the worktree or index. Fix #10: checkout sets the executable bit, and status/diff report mode changes #15 fixes that in diff.ts, and the summary lines will show them once it lands.
  • -q with --summary prints the summary, the same way just-git already handles -q --stat. Git 2.34.1 prints nothing for both. I left this alone because just-git's -q handling follows newer git.
  • --stat, --numstat and -p fail on a commit that adds or removes a gitlink, because they try to read the submodule commit as a blob. --summary alone works (create mode 160000 gm).
  • The -p part of show -p --summary / log -p --summary inherits the existing patch gaps: no old mode/new mode lines, and combined diffs drop the hunk for a file both parents lack. The summary part matches.
  • show --name-status on a merge prints nothing where git prints combined status (MM f).
  • --compact-summary isn't supported, and show -p --stat still prints only the stat.

git log --graph --format=<fmt> --stat (or any other diff output) put
the diff right under the formatted line. Real git separates them with a
padded blank line, the same as without --graph and the same as the
medium format already did here. Only --oneline skips it.
--summary prints git's create, delete, rename and mode-change lines.
show and log print them under each commit and skip merges in log, as
git does. They follow --stat, --shortstat and --numstat, come before a
-p patch with a blank line between, and replace the patch when no other
diff format is given. --name-only and --name-status drop them, and so
does show --no-patch. A commit with changes but no summary lines still
gets the blank line after its message.

The lines come from one formatter in commit-summary.ts, formatSummaryLines,
which commit and merge now use as well. That fixes two things they got
wrong: a mode change printed as a delete plus a create instead of
"mode change 100644 => 100755 <path>", and a rename that also changed the
mode left out the pathless mode line. Paths are C-quoted the way git
quotes them, and a rename with a quoted side prints both sides in full.
git show on a merge prints its patch as a combined diff, but --stat,
--shortstat, --numstat and --summary compare the merge with its first
parent. just-git printed nothing for those formats on a merge, so
show --summary <merge> missed the files the merge brought in. The name
formats still print nothing here, as before.
@blindmansion
blindmansion merged commit 0e2b0c4 into blindmansion:main Oct 14, 2026
2 checks passed
blindmansion added a commit that referenced this pull request Oct 14, 2026
Fold the four changesets into a 1.10.0 section covering Hazzng's PRs #14, #15, #20 and #21 and the follow-up fixes since, with a Changed note for FileSystems without chmod and a known issue for just-bash overwrites dropping the exec bit. The version bump is a separate commit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support --summary in git show, git log and git diff

2 participants