'Diffing a file (not whole branch) in GIT with remote

ALL,

Igors-MacBook-Air:dbhandler igorkorot$ git diff foo/bar.cpp origin/master:foo/bar.cpp 
fatal: origin/master:foo/bar.cpp: no such path in the working tree.
Use 'git <command> -- <path>...' to specify paths that do not exist locally.
Igors-MacBook-Air:dbhandler igorkorot$ git remote -v
origin  [email protected]:oneeyeman1/dbhandler.git (fetch)
origin  [email protected]:oneeyeman1/dbhandler.git (push)

Of course both files do exists - in both local and remote repository.

What am I doing wrong?

TIA!!



Solution 1:[1]

TL;DR

You want:

git diff -R origin/master -- foo/bar.cpp

Longer

The syntax for git diff (as defined by the SYNOPSIS lines in the documentation) includes this form:

git diff [<options>] <commit> <commit> [--] [<path>...]

but not:

git diff [<options>] <path> <commit>:<path>

so:

git diff foo/bar.cpp origin/master:foo/bar.cpp

is simply not acceptable as a set of command line arguments.

There's no direct way to compare just one on-disk file, such as foo/bar.cpp, to a committed file. There is, however, a way to compare the current commit or any other commit to the entire current working tree. For this you need:

git diff [<options>] <commit>

which fits within the first SYNOPSIS line.1 To this, you can—as suggested by that same line—add -- foo/bar.cpp to limit the diff output to just the one named file.

There's one flaw here and that is that the order of the diff output has the named commit's copy of the file on the left, and the working-tree copy of the file on the right. This is the reverse of what you would like. If we were comparing two commits we could just swap the order—that is, if we were doing git diff a123456 b789abc -- foo/bar.cpp we could just run git diff b789abc a123456 instead—but here we can't do that. Fortunately, one of the available options is -R (uppercase), meaning reverse: swap the left and right sides of the diff.

While this implicitly diffs the entire commit against the entire working tree (and then limits the displayed results to the one file if it's different), Git optimizes the operation internally.


1In a SYNOPSIS line, square brackets [...] indicate something optional and angle brackets <...> indicate that something is required here but you must supply it. So [<options>] indicate that the options are optional and come from the set of options described later in the document, while [--] is an optional literal -- and <path> is an optional path name. The three dots ... after <path> indicate that it can be repeated, in case you want to show more than one diff for the selected commit.

The purpose of the -- here, which is optional but which I included, is to make sure that no path argument gets misinterpreted as a commit specifier (perhaps you have a branch named foo/bar.cpp for instance: that's a legal branch name!) or an option. The latter wouldn't happen anyway, since options start with - and foo does not start with -, but using the double hyphen is a good habit to establish in case you find yourself with a file named -f or -R or whatever.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1