Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check real git diff before merging from remote branch?

Tags:

git

diff

I want to check the real diff between remote branch and local branch. How can I do that?

Issuing the below command partially works, but it shows the diff of the new changes of my local branch too.

git diff remote/branch
like image 909
abhiomkar Avatar asked Feb 09 '11 11:02

abhiomkar


People also ask

How do I tell the difference between local and remote?

You can git branch -a to list all branches (local and remote) and then choose the branch name from the list (just remove remotes/ from the remote branch name. Example: git diff main origin/main (where "main" is the local main branch and "origin/main" is a remote, namely the origin and main branch.)

How do I see my git diffs?

The diff can be done with git diff (followed by the filename or nothing if you want to see the diff of all modified files). But if you already did something like git add * , you have to undo with git restore --staged .


3 Answers

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:

origin/master remotes/origin/master refs/remotes/origin/master 

To begin to untangle this, just take a peek at your repository's .git directory structure. A typical layout looks like this:

.git/refs .git/refs/heads .git/refs/heads/master .git/refs/remotes .git/refs/remotes/origin .git/refs/remotes/origin/HEAD .git/refs/remotes/origin/master .git/refs/tags 

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:

ref: refs/remotes/origin/master 

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      6d0fb0adfdfa5af861931bb06d34100b349f1d63 

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 git pull.

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 at git-scm revision selection: 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.

like image 111
rholmes Avatar answered Sep 24 '22 11:09

rholmes


From the documentation:

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

This form is to view the changes on the branch containing and up to the second <commit>, starting at a common ancestor of both <commit>. "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B". You can omit any one of <commit>, which has the same effect as using HEAD instead.

did you try this?

like image 34
Evgen Bodunov Avatar answered Sep 21 '22 11:09

Evgen Bodunov


What you want to do is, as suggested by Evgen Bodunov:

git diff ...remote/branch

This will diff changes from remote/branch and ignore changes from your current HEAD.

like image 44
Antoine Pelisse Avatar answered Sep 24 '22 11:09

Antoine Pelisse