535

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.

Peter Mortensen
31.3k22 gold badges110 silver badges134 bronze badges
asked Jan 12, 2009 at 18:03
2
  • The coolest thing about this would be that this would work with "git difftool", using the tools to show the diff. Commented Jul 6, 2010 at 11:38
  • For reference, the answer to this other question illustrates how you could set up a bash-powered alias to simplify the above: stackoverflow.com/questions/3321492/… Commented Sep 20, 2012 at 11:40

8 Answers 8

712

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

answered Jan 12, 2009 at 18:06
Sign up to request clarification or add additional context in comments.

13 Comments

Too bad it can't use difftool :(
@orip you can always set GIT_EXTERNAL_DIFF to a script that does the same thing as your difftool.
I prefer JakubNarebski's answer, as the commit expression given there will work in many contexts: stackoverflow.com/a/449128/992887
If there is not diff shown, there probably are no actual changes, like for a merge commit
@PTWithy: The question was, "Is there a shorter command for getting the diff for a particular commit?", which this question answers.
|
516

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.

7 Comments

This should be the accepted answer, it's much neater. However, the last sentence of the git-rev-parse extract is rather confusing - seems like it means 'range from this commit's parent to this commit'.
@RichVel: it is a bit confusing because it tries to describe also the situation where commit has more than one parent (is a merge commit). r1^! works as expected also then.
@JakubNarębski: good point, maybe you could edit your answer to summarise your understanding of the single-parent and multi-parent cases - separate statements on each might be easier to understand.
@JakubNarębski: yes, much better! I now use this shortcut all the time - thanks.
The ^! parent shorthand notation works properly with difftool for normal commits but the diff is reversed for merge commits. Why so?
|
60

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.

answered Jan 12, 2009 at 19:34

1 Comment

HEAD^2 is not the grandparent, if HEAD^1 is daddy, then HEAD^2 is mommy. Use HEAD~2 for daddy's daddy.
12

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.

Peter Mortensen
31.3k22 gold badges110 silver badges134 bronze badges
answered Mar 14, 2012 at 9:16

2 Comments

This alias can include --color which makes it easier to read: sd = show --color --pretty=format:%b
@RichVel Indeed! Very good point. If you have colors enabled by default in git, you won't need this switch, though. That's what I normally do.
6

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\^\!

Peter Mortensen
31.3k22 gold badges110 silver badges134 bronze badges
answered Aug 20, 2014 at 2:05

1 Comment

4. single-quote the refs, e.g., git diff '15dc8^!'
4

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
Peter Mortensen
31.3k22 gold badges110 silver badges134 bronze badges
answered Dec 6, 2013 at 12:08

Comments

3
git diff 15dc8 15dce~1

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

answered Nov 26, 2012 at 15:40

Comments

0

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"
Peter Mortensen
31.3k22 gold badges110 silver badges134 bronze badges
answered May 2, 2012 at 6:28

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.