Reputation: 5805
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?
Upvotes: 1
Views: 3416
Reputation: 487775
I recommend avoiding git pull
. What git pull
does is:
git fetch
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.
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.)
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.
git merge
would mergeWhen 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.
git diff
command that does this for youGit'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".
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.
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.
Upvotes: 4
Reputation: 933
You can see the difference with below command
git diff (local-branch) (remote-branch)
OR
Upvotes: 1