386

How can I diff a file, say pom.xml, from the master branch to an arbitrary older version in Git?

BuZZ-dEE
  • 4,936
  • 10
  • 57
  • 84
Chris K
  • 11,566
  • 7
  • 36
  • 63

13 Answers13

413

You can do:

git diff master~20:pom.xml pom.xml

... to compare your current pom.xml to the one from master 20 revisions ago through the first parent. You can replace master~20, of course, with the object name (SHA1sum) of a commit or any of the many other ways of specifying a revision.

Note that this is actually comparing the old pom.xml to the version in your working tree, not the version committed in master. If you want that, then you can do the following instead:

git diff master~20:pom.xml master:pom.xml
Mark Longair
  • 415,589
  • 70
  • 403
  • 320
  • 17
    Note that this doesn't just work for files, it also works for (sub)directories as well, for example `git diff :foo/ HEAD:foo/`. –  Jul 05 '14 at 18:59
  • 2
    Also note that on windows you need to use forward slashes for directories if you are using a revision specifier or git will give you an error about the file/directory not existing in that revision. – Dylan Nissley Nov 21 '14 at 13:38
  • 1
    @DylanNissley or it will give you no error and no diff. That's what I see. In any case, thank you for the hint about using forward slashes instead of backslashes. – Gary Sheppard Aug 17 '17 at 20:05
  • With windows files I've found it easier to change directory and then call git diff master~20:./pom.xml ./pom.xml – lloyd Aug 24 '18 at 06:16
  • Some version of git require "--" between the & – Josh Apr 27 '20 at 03:36
167
git diff <revision> <path>

For example:

git diff b0d14a4 foobar.txt
Benjamin Pollack
  • 26,542
  • 16
  • 78
  • 103
  • does not work for version 1.7.11 if file is not in current directory. Example: 'git diff f76d078 test/Config' yields "error: Could not access 'test/f76d078'" – simpleuser Dec 04 '13 at 21:21
  • 2
    @user1663987 just pass a full path relative to the project root: `git diff root/path/file`. –  Jun 27 '14 at 17:23
  • 1
    test/Config *is* relative to the root (as in test is a sub-directory of the root). but then your example root/path/file would seem to INCLUDE the root? – simpleuser Jun 29 '14 at 05:55
53

If you want to see the difference between the last commit of a single file you can do:

git log -p -1 filename

This will give you the diff of the file in git, is not comparing your local file.

Gerardo
  • 6,999
  • 3
  • 20
  • 17
  • 2
    this is not returning anything – Andrei Cristian Prodan Oct 17 '14 at 12:05
  • @AndreiCristianProdan Then you have no changes there. You can increment the `-1` step by step until you get the changes. – kaiser Oct 30 '14 at 11:30
  • This is very nice. I created a bash function that might be useful: `gitlog () { git log -${3:-p} -${2:-1} $1; }` Used like: `gitlog Rakefile` or `gitlog Rakefile 5` and `gitlog Rakefile 10 s`. The first shows one diff; the second shows five diffs; the third shows ten `--no-patch`. – auxbuss Jun 07 '18 at 13:12
36

To see what was changed in a file in the last commit:

git diff HEAD~1 path/to/file

You can change the number (~1) to the n-th commit which you want to diff with.

Juampy NR
  • 2,448
  • 1
  • 23
  • 20
  • This answer is really just a specific case of [this more general answer](http://stackoverflow.com/a/5586434/456814), where `HEAD~1` is substituted for ``, which makes this answer a duplicate. –  Jul 17 '14 at 21:52
  • 2
    this isn't working! fatal: ambiguous argument 'HEAD~1': unknown revision or path not in the working tree. Use '--' to separate paths from revisions – Andrei Cristian Prodan Oct 17 '14 at 12:04
  • This answer is simple and functional for me. – Douglas Frari May 09 '19 at 11:46
10

Generic Syntax :

$git diff oldCommit..newCommit -- **FileName.xml > ~/diff.txt

for all files named "FileName.xml" anywhere in your repo.

Notice the space between "--" and "**"

Answer for your question:

$git checkout master
$git diff oldCommit..HEAD -- **pom.xml 
or
$git diff oldCommit..HEAD -- relative/path/to/pom.xml 

as always with git, you can use a tag/sha1/"HEAD^" to id a commit.

Tested with git 1.9.1 on Ubuntu.

soundslikeodd
  • 1,097
  • 2
  • 24
  • 30
7

If neither commit is your HEAD then bash's brace expansion proves really useful, especially if your filenames are long, the example above:

git diff master~20:pom.xml master:pom.xml

Would become

git diff {master~20,master}:pom.xml

More on Brace expansion with bash.

robstarbuck
  • 5,087
  • 1
  • 35
  • 35
7

For comparing to 5 commit to the current one, both on master, just simply do:

git diff master~5:pom.xml master:pom.xml

Also you can refer to commit hash number, for example if the hash number is x110bd64, you can do something like this to see the difference:

git diff x110bd64 pom.xml
Alireza
  • 93,149
  • 25
  • 259
  • 162
5
git diff -w HEAD origin/master path/to/file
NerdOnTour
  • 396
  • 1
  • 11
CatalinBerta
  • 1,346
  • 17
  • 17
2
git diff master~20 -- pom.xml

Works if you are not in master branch too.

Gunar Gessner
  • 1,861
  • 20
  • 20
2

If you are fine using a graphical tool (or even prefer it) you can:

gitk pom.xml

In gitk you can then click any commit (to "select" it) and right click any other commit to select "Diff this -> selected" or "Diff selected -> this" in the popup menu, depending on what order you prefer.

Martin G
  • 16,009
  • 9
  • 78
  • 91
0

For people interested in doing the same from GitHub, see comparing commits across time.

Skippy le Grand Gourou
  • 5,996
  • 4
  • 52
  • 70
0

If you need to diff on a single file in a stash for example you can do

git diff stash@{0} -- path/to/file
lacostenycoder
  • 9,787
  • 4
  • 28
  • 43
-1

If you are looking for the diff on a specific commit and you want to use the github UI instead of the command line (say you want to link it to other folks), you can do:

https://github.com/<org>/<repo>/commit/<commit-sha>/<path-to-file>

For example:

https://github.com/grails/grails-core/commit/02942c5b4d832b856fbc04c186f1d02416895a7e/grails-test-suite-uber/build.gradle

Note the Previous and Next links at the top right that allow you to navigate through all the files in the commit.

This only works for a specific commit though, not for comparing between any two arbitrary versions.

Schmick
  • 200
  • 1
  • 11