How to diff a commit with its parent

GitGit Diff

Git Problem Overview


Aside from writing an alias or script, is there a shorter command for getting the diff for a particular commit?

git diff 15dc8^..15dc8

If you only give the single commit id git diff 15dc8, it diffs that commit against HEAD.

Git Solutions


Solution 1 - Git

Use git show $COMMIT. It'll show you the log message for the commit, and the diff of that particular commit.

Solution 2 - Git

Use:

git diff 15dc8^!

as described in the following fragment of git-rev-parse(1) man page (or in modern Git gitrevisions(7) man page):

> Two other shorthands for naming a set that is formed by a commit and its > parent commits exist. The r1^@ notation means all parents of r1. r1^! > includes commit r1 but excludes all of its parents.

This means that you can use 15dc8^! as a shorthand for 15dc8^..15dc8 anywhere in Git where revisions are needed. For the diff command, the git diff 15dc8^..15dc8 is understood as git diff 15dc8^ 15dc8, which means the difference between parent of commit (15dc8^) and commit (15dc8).

Note: the description in git-rev-parse(1) man page talks about revision ranges, where it needs to work also for merge commits, with more than one parent. Then r1^! is "r1 --not r1^@" i.e. "r1 ^r1^1 ^r1^2 ..."


Also, you can use git show COMMIT to get the commit description and diff for a commit. If you want only the diff, you can use git diff-tree -p COMMIT.

Solution 3 - Git

If you know how far back, you can try something like:

# Current branch vs. parent
git diff HEAD^ HEAD

# Current branch, diff between commits 2 and 3 times back
git diff HEAD~3 HEAD~2

Prior commits work something like this:

# Parent of HEAD
git show HEAD^1

# Grandparent
git show HEAD^2

There are a lot of ways you can specify commits:

# Great grandparent
git show HEAD~3

See this page for details.

Solution 4 - Git

As mipadi points out, you can use git show $COMMIT, but this also shows some headers and the commit message. If you want a straight diff, use git show --pretty=format:%b $COMMIT.

This is, obviously not a very short hand, so I'm keeping this alias in my .gitconfig

    [alias]
      sd = show --pretty=format:%b

This enables me to use git sd $COMMITto show diff.

Solution 5 - Git

Many of the mentioned examples (e.g. git diff 15dc8^!, or git diff 15dc8^..15dc8) don't work if you are using Z shell and have extendedglob option set. You can fix it by one of the following three ways:

  1. unsetopt extendedglob (and/or remove it from .zshrc)

  2. setopt NO_NOMATCH (and/or set it in .zshrc)

  3. escape the caret and bang every time with a backslash, e.g., git diff 15dc8\^\!

Solution 6 - Git

git diff 15dc8 15dce~1

~1 means 'parent', ~2 'grandparent, etc.

Solution 7 - Git

Paul's solution did what I was hoping it would.

$ git diff HEAD^1

Also, it's useful to add aliases like hobs mentioned. If you put the following in the [alias] section of your ~/.gitconfig file then you can use the shorthand to view diff between head and previous.

[alias]
    diff-last = diff HEAD^1

Then running $ git diff-last will get you your result. Note that this will also include any changes you've not yet committed as well as the diff between commits. If you want to ignore changes you've not yet committed, then you can use diff to compare the HEAD with its parent directly:

$ git diff HEAD^1 HEAD

Solution 8 - Git

This uses aliases, so it doesn't answer your question exactly, but I find these useful for doing what you intend...

alias gitdiff-1="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 2|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"
alias gitdiff-2="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 3|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"
alias gitdiff-3="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 4|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"

alias gitlog-1="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 2|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
alias gitlog-2="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 3|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
alias gitlog-3="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 4|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBrian LView Question on Stackoverflow
Solution 1 - GitmipadiView Answer on Stackoverflow
Solution 2 - GitJakub NarębskiView Answer on Stackoverflow
Solution 3 - GitPaul Vincent CravenView Answer on Stackoverflow
Solution 4 - GitØystein SteimlerView Answer on Stackoverflow
Solution 5 - GitVilleView Answer on Stackoverflow
Solution 6 - GitJohn Lawrence AspdenView Answer on Stackoverflow
Solution 7 - GitGraham R. ArmstrongView Answer on Stackoverflow
Solution 8 - GithobsView Answer on Stackoverflow