skip to content

What does git show display for a commit, and how does it differ from git diff?

level: juniorimportance: should knowfreq 45%

answer

  1. One object versus one comparison
  2. Metadata plus a patch
  3. Which parent does it diff against?
  4. Merges get a combined diff
  5. Colon syntax prints file contents

basics

~20 s

git show prints one object: for a commit it prints the metadata and log message plus the patch against its first parent. git diff prints only a patch between two snapshots and never shows commit metadata.

solid answer

~50 s

`git show <commit>` displays a single object. For a commit that means the author, date, full log message and then the patch introduced by that commit relative to its first parent; with no argument it defaults to `HEAD`. `git diff` never prints metadata — it renders the difference between two trees you name (or the working tree and the index by default). So `git show <c>` is roughly `git log -1 <c>` plus `git diff <c>^ <c>`, in one command. `git show` also works on other object types: `git show <tag>` prints the annotated tag object and the commit it points at, and `git show <commit>:<path>` prints the *contents* of that file as of that commit, which is the quickest way to read an old version without checking anything out. All the usual diff options apply, e.g. `git show --stat <commit>`.

go deeper

for a junior

Know that git show defaults to HEAD and prints commit metadata plus the patch, and that git show <commit>:<file> prints an old version of a file. Those two uses cover most day-to-day needs.

for a middle

Explain that a commit's patch is defined against its first parent, and that merge commits are rendered as a combined diff showing only hunks differing from all parents.

for a senior

Demonstrate fluency mixing show with diff options — --stat, pathspec limiting, -m for merges — and know when git log -p is the right tool instead because you need a range rather than one commit.

for a principal

Talk about how single-commit inspection habits shape review culture: commits that are readable one at a time under git show are the ones a team can bisect, revert and audit later.

## What git show is for `git show` is the "tell me about this one object" command. Given a revision it resolves the object, prints an appropriate header for its type, and — when the object is or points to a commit — appends the patch that commit introduced. `git diff`, by contrast, is a pure comparison engine: it takes two snapshots and renders their difference, with no notion of authorship, date or message. With no argument, `git show` operates on `HEAD`, so it is the fastest way to re-read the commit you just made. ## A commit `git show <commit>` prints: 1. The commit id, and merge information if applicable. 2. Author name and email, author date, and (when it differs from the author) the committer. 3. The full commit message, indented. 4. The patch of that commit against its **first parent**. That last point is the one to internalize: a commit's "changes" are only well defined relative to a parent, and Git picks the first one. `git show <commit>` is therefore approximately `git diff <commit>^ <commit>` with a header on top. ## A merge commit Merge commits have more than one parent, so "the patch" is ambiguous. `git show` handles this with a **combined diff** (the dense `--cc` form): rather than showing the merge against each parent separately, it shows only the hunks where the merge result differs from *all* of its parents. In practice that means a clean, purely mechanical merge shows almost no diff, while hunks that the merge resolved by hand — or edits made during conflict resolution — do appear. The output has two columns of `+`/`-` markers, one per parent, instead of one. If you want the merge against a specific parent instead, `git show -m` splits it into one diff per parent, and `git show --first-parent` restricts it to the first. ## Other object types - **`git show <tag>`** on an annotated tag prints the tag object — tagger, date, tag message — and then follows through to the commit it points at, printing that commit's header and patch too. A lightweight tag is just a name for a commit, so it behaves like showing the commit. - **`git show <commit>:<path>`** prints the raw *content* of that path as it existed in that commit. This is the everyday way to read an old version of a file: `git show HEAD~5:src/config.yaml`. Note the path here is relative to the repository root, not to your current directory, unless you write it as `./relative/path`. - **`git show <tree>`** lists the entries of a tree object. ## Options carry over from diff Because the patch part is produced by the same machinery, essentially all diff formatting options work: `git show --stat <commit>` gives the per-file summary instead of the full patch, `git show --name-only <commit>` lists just the touched paths, `git show -w <commit>` ignores whitespace, and `git show <commit> -- <path>` limits the patch to a path. Log-formatting options apply to the header: `git show --format=%s <commit>` prints just the subject line. ## When to use which Use `git show` when the unit you care about is **one commit** — reviewing what a colleague pushed, checking your own last commit before force-pushing, or reading a file at a revision. Use `git diff` when the unit you care about is **the difference between two states** — your uncommitted work, the gap between a feature branch and its base, or the change across a release range. `git log -p` sits between them: it is `git show`'s output repeated for every commit a revision walk produces. ## A common confusion People sometimes expect `git show <branch>` to display the branch's whole content or its full history. It does not: a branch name resolves to a single commit (its tip), so `git show main` shows one commit — the newest one on `main`. To see the accumulated difference between branches you want `git diff`, and to see the list of commits you want `git log`.

  • Why does git show on a clean merge commit often display almost no diff?
    Because git show renders merges as a combined diff, listing only hunks that differ from every parent. A merge that took each change unmodified from one side or the other matches some parent everywhere, so there is nothing to display. Use git show -m to see the merge against each parent separately.
  • How do you read the contents of a file as it was five commits ago without checking anything out?
    git show HEAD~5:path/to/file prints the blob's content straight to stdout, so you can pipe or redirect it. The path is interpreted from the repository root; prefix it with ./ to make it relative to your current directory.
  • What does git show print when given a branch name?
    A single commit — the branch tip — with its metadata and patch, not the branch's history or full contents. A branch name is just a pointer to one commit, so use git log for the commit list and git diff for the accumulated difference against another ref.

saying these in an interview costs you the question

  • Thinks git show prints a branch's whole history
  • Expects a commit patch without naming a parent
  • Believes git diff also prints commit messages
  • Thinks git show cannot display file contents
  • Assumes merge commits show a plain single-column patch

context