Since this topic comes up frequently, and can be confusing without a bit of background on how git works, I thought I'd try to explain the simplest case possible, but with sufficient depth that newcomers will have enough of a handle on it to do additional research.
If you set up your git repository via a normal 'clone' and have the default refspecs, meaning that your remote is named 'origin' and you pull/fetch from the branch 'master', you may sometimes need to see what's in the remote repository before pulling it down.
Since the "git pull" does an automatic merge (unless there are conflicts), it can be nice to see what's "incoming" next. If you're not familiar with how git works, and how refspecs in particular are managed, this can be a bit non-intuitive.
Suppose someone makes a change in the remote repository (for sake of illustration, adding a line to the remote repository by committing a change and pushing it), and you type:
$ git diff origin/master
You probably won't see any changes; however if you do the following:
$ git fetch; git diff ..origin/master
you'll see the difference between what's been committed to your local git repository and what's in the remote repository. You will NOT see any changes which are in your local filesystem or staged in your index.
Ok, why do we do this? origin/master is a refspec (see man pages). In short, this is what we refer to in order to compare against, pull or fetch from, and push to. All of the following are functionally equivalent:
To begin to untangle this, just take a peek at your repository's .git directory structure. A typical layout looks like this:
Look at .git/refs/remotes/origin/HEAD; in the default case it will point to the branch you use to pull from and push to. In my case, since I'm on master, the contents of this text file look like this:
This tells me that the HEAD of my remote is identified by the refspec 'refs/remotes/origin/master'(which happens to have the aliases mentioned above).
This doesn't tell us much; what's the state of the remote repository? Look at the state of the remote master:
$ cat .git/refs/heads/master
Ok, it's a SHA1 hash; probably a commit. How does it get put in this file? Well, whenever you do a pull or a fetch, this file is updated with the most recent commit from the remote which was pulled or fetched. This explains why we have to
git fetch prior to performing the diff. Remember,
git fetch just updates your local copy of a remote branch, but doesn't merge it with your working copy. It is completely safe. A
git fetch; git merge is equivalent to a
Once you do the fetch, git will be able to see the most recent commit in the remote repository as of the time of the fetch.
You can use various combinations of specifiers to git to see your diffs as you desire (the following examples use the local working copy as the implicit first commit):
$ git diff remote/origin
This shows the incoming remote additions as deletions; any additions in your local
repository are shown as additions.
$ git diff ...remote/origin
Shows incoming remote additions as additions; the triple-dot excludes changes
committed to your local repository.
$ git diff ..remote/origin
Shows incoming remote additions as additions; the double-dot includes changes
committed to your local repository as deletions (since they are not yet pushed).
For info on ".." vs "..." see
git help diff as well as the excellent documentation git-scm commit ranges. Briefly, for the examples above, double-dot syntax shows all commits reachable from origin/master but not your working copy. Likewise, the triple-dot syntax shows all the commits reachable from either commit (implicit working copy, remote/origin) but not from both.
I'm going through this step by step because I'm fairly new to git and this is exactly the type of thing that had me confused... I'm sure that git experts can find flaws with the details... I just hope this answer bridges the gap for some people who find all the various posts a bit terse.