1

I have a local repository with XXX branch. I want to check if there are changes in master branch (which I could integrate into my XXX).

git pull would apply the changes to my local repository, but I want first to check if there are changes without actually applying them.

How?

porton
  • 5,214
  • 11
  • 47
  • 95

3 Answers3

4

I recommend avoiding git pull. What git pull does is:

  1. run git fetch
  2. run a second Git command, usually git merge (but you can choose git rebase instead)

without stopping between them. This is meant to be convenient, but, well, it isn't. (Pull also supplies particular arguments to each of the two Git commands, but this isn't required in general, and obscures all the real action.)

What you'd like to do is see what git merge might do after git fetch. The git pull command won't let you do that—it will run the git fetch and then run the second Git command immediately.

TL;DR: run git fetch first, then look around, then—after you've decided it's a good idea—you can run the second Git command that git pull would run.


Using git fetch

Hence, just run git fetch yourself. This will make your Git call up the other Git, the one at origin. Your Git will ask their Git: Hey, what branches do you have? What are the hash IDs for the commits for your master and your other branches?1 When your Git gets the answers, your Git will then download, from their Git, all the commits and such that you need—the commits they have that you don't—and will then remember which commit was their master, by putting that hash ID into your origin/master, and so on. Essentially, your Git now has, locally, all of their branches, but under the origin/* names, so that they don't interfere in any way with any of your own branches.

Note that unlike git pull, it's safe to run git fetch at any time. The fetch operation will not wreck anything you are in the middle of working on. This does assume you don't get overly creative with special git fetch options or refspecs, and just stick with git fetch or git fetch origin. (In particular you need to avoid --update-head-ok, which is one of git pull's special flags that makes git pull kind of dangerous—git pull tries to make sure it's safe but has historically gotten this wrong now and then—and you should not run git fetch +refs/*:refs/* since this will overwrite all your own branches. But git fetch origin is quite safe.)

Looking at what you have

Now that you have all of their commits plus all of your own commits, you can look around at everything. I like to use git log --graph, particularly git log --all --decorate --oneline --graph, for which Patoshi gave us this nice mnemonic, "help from A DOG" (see Pretty git branch graphs and linked posts). This "looking around" is how you really tell what git merge will do, if you choose to merge.2 It's also how you tell what git rebase will do, if you choose instead to rebase.

What git merge would merge

When you run git merge, you will, in general, first check out some branch. This is where Git will put the merge result, but it's also one of the inputs to git merge itself. You then run git merge thing.3 So you have two particular commits to consider. Typically, you would specify these using two names like master—the branch you will check out—and origin/master. The names don't have to be branch names, and this second one here isn't, quite: origin/master isn't a branch name in the sense of naming one of your branches. Again, it's just your Git's way of remembering their Git's branch. See also What exactly do we mean by "branch"?

To see what a merge would do, you would normally have to do:

git merge-base --all master origin/master

which finds all the merge base commits for these. Usually there's only one, and usually we just assume there's only one (because things get complicated and hairy when there are several). You'd then do:

git diff <that-hash> master         # to see what we did since then
git diff <that-hash> origin/master  # to see what they did

since this gives you the set of all the changes that git merge will need to merge.

Merge is about combining changes. To combine changes, merge has to find a common starting point, and then find both sets of changes. That means that there are three inputs: your current branch, the other branch, and the merge base.

The fancy git diff command that does this for you

Git's diff command has a special rule built into it just for this merge case. No other Git command behaves like this, but if you take those two names, master and origin/master for instance, and put three dots between them:

git diff origin/master...master

Git will find the4 merge base and diff that against master: that will be "what you did". You can then reverse the two names around the three-dot operation:

git diff master...origin/master

and Git will again find the merge base, but this time diff that against origin/master, to see "what they did".

Rebase

I won't get into rebase here, but I'll note that what git rebase really does is to copy some existing commits to new-and-improved commits. If you've been working on some branch B, and your upstream origin/B has acquired new commits, you can rebase your commits on the latest upstream. This has advantages and disadvantages. It's considerably more complicated than merging—in fact, each commit that is copied is a tiny little mini-merge—but many people prefer it to give the illusion of a simple development history, instead of the reality of a complex and chaotic history. As with merging, visualizing the commit graph is a key to understanding rebase.

Conclusion

To see what you're going to get, you need to visualize the commit graph (git log with A DOG, git log --all --decorate --oneline --graph) and/or inspect changes (git diff B...origin/B and git diff origin/B...B). You literally can't do that with git pull because you have to do it between the git fetch step and the git merge step. This, plus many other annoying bits, is what makes git pull an inconvenient command.


1You can see just what their Git tells your Git by running git ls-remote origin. This does the same thing as git fetch, except that it stops right after collecting their branch names and hash IDs, and then shows you what it collected.

2There's much more you can do as well, but visualizing the graph topology or otherwise finding the merge base is one of the keys to understanding git merge.

3Once your branch has an upstream set, you can just run git merge: Git will pick out the upstream. Typically, the upstream for master is origin/master, so once you git checkout master, git merge by itself means git merge origin/master. You can always specify the particular thing you want to merge, though, and if you're merging two of your own branches, you will usually have to do that (though it's possible to set one of your own branches as the upstream of another of your own branches!).

4If there are multiple merge bases, git diff will just pick one of them. This is not quite right, but usually works well enough.

torek
  • 448,244
  • 59
  • 642
  • 775
1

You can see the difference with below command

git diff (local-branch) (remote-branch)

OR

click here for more details

zubair khanzada
  • 903
  • 2
  • 9
  • 15
0

This should do it,

$ git diff <masterbranch_path> <remotebranch_path>

You may also want to look at git fetch.

evilSnobu
  • 24,582
  • 8
  • 41
  • 71