The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,860 other subscribers

version control – How can I see the changes in a Git commit? – Stack Overflow

Posted by jpluimers on 2025/12/16

[Wayback/Archive] version control – How can I see the changes in a Git commit? – Stack Overflow (thanks [Wayback/Archive] laktak, [Wayback/Archive] Nevik Rehnel, [Wayback/Archive] Juuso Ohtonen and [Wayback/Archive] User c z – Stack Overflow)

This looks like a valid question, but in reality it is not.

The thing is: in git, think of a commit not as a diff but as a snapshot*.

A diff is the difference between two commits.

Since most commits have just a single parent, so that’s why many people call a commit a diff. But that’s not true, especially not for merge commits that have at least two parents.

Anyway, the question, answer and comment from the link above already give some insight (note COMMIT everywhere below has to be replaced with the commit hash):

Q

When I do git diff COMMIT I see the changes between that commit and HEAD (as far as I know), but I would like to see the changes that were made by that single commit.

I haven’t found any obvious options on diff / log that will give me that output.

A

To see the diff for a particular COMMIT hash, where COMMIT is the hash of the commit:

git diff COMMIT~ COMMIT will show you the difference between that COMMIT‘s ancestor and the COMMIT. See the man pages for git diff for details about the command and gitrevisions about the ~ notation and its friends.

Alternatively, git show COMMIT will do something very similar. (The commit’s data, including its diff – but not for merge commits.) See the git show manpage.

(also git diff COMMIT will show you the difference between that COMMIT and the head.)

C

git diff COMMIT~ COMMIT works for me, notice the tilde instead of caret. I’m running git version 2.6.1.windows.1 on Windows 10.

C

If you’re not getting the diff it may be a merge commit. You need git show <COMMIT> --diff-merges=on in this case.

A better StackoverFlow Q/A

[Wayback/Archive] How to “git show” the diffs for a merge commit? – Stack Overflow (thanks [Wayback/Archive] Sohaib Farooqui and [Wayback/Archive] torek) is a much better start as the answer goes in much greater depth explaining merge commits than I quoted here:

Q

When I have a merge commit and run git show <commit-ish>, it shows only the commit log, not the the diffs:

commit c0f50178901e09a1237f7b9d9173ec5d1c4936c
Merge: ed234b ded051
Author: abc
Date:   Mon Nov 21 15:56:33 2016 -0800

    Merge branch 'abc'

I understand the real commit is in merge log, but I want to save typing. Is there a way to show the diff in one?

A

Use one of the following:

git show -m c05f017
git show --first-parent c05f017
git diff c05f017^ c05f017

There’s a fundamental error in your question: commits are not diffs; commits are snapshots. This might seem like a distinction without a difference—and for some commits, it is. But for merge commits, it’s not.

When git show (or git log -p) shows a commit as a diff, it’s doing so by comparing the commit’s snapshot to something else. The git diff command does the same thing: it compares one commit to another commit. (Or it can compare a commit to the work-tree, or to the contents of the index, or a few other combinations as well.)

For ordinary commits, it’s trivially obvious what to compare: compare this commit’s snapshot to the previous (i.e., parent) commit’s snapshot. So that is what git show does (and git log -p too): it runs a git diff from the parent commit, to this commit.

Merge commits don’t have just one parent commit, though. They have two parents.1 This is what makes them “merge commits” in the first place: the definition of a merge commit is a commit with at least two parents.


1A merge commit can have three or more parents. These are called “octopus merges”. They don’t do anything special, though, and are mainly for showing off. :-) You can ignore them here.

git show defaults to --cc

* the commit as a snapshot

I took a shortcut in the introduction.

Actually, a git tree object is the snapshot and a commit object contains the timestamp, log message and references to the tree and parent commit objects (usually one parent, but as I wrote above: two or more for merge commits).

Documentation references

  • [Wayback/Archive] Git – git-diff Documentation
  • [Wayback/Archive] Git – gitrevisions Documentation

    Dotted Range Notations

    The .. (two-dot) Range Notation
    The ^r1 r2 set operation appears so often that there is a shorthand for it. When you have two commits r1 and r2 (named according to the syntax explained in SPECIFYING REVISIONS above), you can ask for commits that are reachable from r2 excluding those that are reachable from r1 by ^r1 r2 and it can be written as r1..r2.
    The  (three-dot) Symmetric Difference Notation
    A similar notation r1…r2 is called symmetric difference of r1 and r2 and is defined as r1 r2 –not $(git merge-base –all r1 r2). It is the set of commits that are reachable from either one of r1 (left side) or r2 (right side) but not from both.

    In these two shorthand notations, you can omit one end and let it default to HEAD. For example, origin.. is a shorthand for origin..HEAD

    <rev>^[<n>], e.g. HEAD^, v1.5.1^0

    A suffix ^ to a revision parameter means the first parent of that commit object. ^<n> means the <n>th parent (i.e. <rev>^ is equivalent to <rev>^1). As a special rule, <rev>^0 means the commit itself and is used when <rev> is the object name of a tag object that refers to a commit object.

    <rev>~[<n>], e.g. HEAD~, master~3

    A suffix ~ to a revision parameter means the first parent of that commit object. A suffix ~<n> to a revision parameter means the commit object that is the <n>th generation ancestor of the named commit object, following only the first parents. I.e. <rev>~3 is equivalent to <rev>^^^ which is equivalent to <rev>^1^1^1.

  • [Wayback/Archive] Git – git-show Documentation is a tremendously versatile command with many parameters, so only a few are included below:

    -p
    -u
    --patch

    Generate patch (see section on generating patches).

    --diff-merges=(off|none|on|first-parent|1|separate|m|combined|c|dense-combined|cc|remerge|r)
    --no-diff-merges

    --diff-merges=on
    --diff-merges=m
    -m

    This option makes diff output for merge commits to be shown in the default format. -m will produce the output only if -p is given as well. The default format could be changed using log.diffMerges configuration parameter, which default value is separate.

    --diff-merges=separate

    This makes merge commits show the full diff with respect to each of the parents. Separate log entry and diff is generated for each parent.

    --diff-merges=combined
    --diff-merges=c
    -c

    With this option, diff output for a merge commit shows the differences from each of the parents to the merge result simultaneously instead of showing pairwise diff between a parent and the result one at a time. Furthermore, it lists only files which were modified from all parents. -c implies -p.

    --diff-merges=dense-combined
    --diff-merges=cc
    --cc

    With this option the output produced by --diff-merges=combined is further compressed by omitting uninteresting hunks whose contents in the parents have only two variants and the merge result picks one of them without modification. --cc implies -p.

Related blog-posts

Queries

–jeroen

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.